当前位置: 首页 > 知识库问答 >
问题:

从派生类C++访问整个基类

涂浩皛
2023-03-14

我理解您可以从派生类访问基类的成员,然而,我有一个函数需要指向我的基类作为一个整体的指针。例如:

#include <iostream>
 
using namespace std;

function foo(Shape &s){
//does something
}

// Base class
class Shape {
   public:
      Shape(int w = 100, int h = 100){
         width = w;
         height = h;
      }
      void setWidth(int w) {
         width = w;
      }
      void setHeight(int h) {
         height = h;
      }
      
   protected:
      int width;
      int height;
};

// Derived class
class Rectangle: public Shape {
   public:
      Rectangle(){
        Shape();
      }
      int getArea() { 
         return (width * height); 
      }
};

int main(void) {
   Rectangle Rect;
   foo(// Pointer Reference to Rect.Shape here);

   return 0;
}

有没有办法从派生类中获得指向这个基类的指针?

共有1个答案

单于楚
2023-03-14

这是您的代码的工作版本。我对其进行了一些更改,并添加了注释来解释更改。您的程序需要多态性以达到预期的行为,否则您将‘切片’您的派生对象,而只有一个基对象。

#include <iostream>
#include <string>

// Base class
// Your base should only have things that would be common to all derived classes
// Consider what the width and height of a Circle would be
//
// You may not have gotten to virtual functions and polymorphism yet. This is
// how you would set up an interface for your Derived classes. I am requiring
// any derived class to implement getArea() and identify() if it wants to be a
// 'concrete' class. Otherwise it will be abstract, which means you can't
// declare objects of that type. It is not possible to declare a Shape object
// because of the pure virtual functions
class Shape {
 public:
  virtual ~Shape() = default;          // A virtual destructor is required
  virtual double getArea() const = 0;  // Pure virtual function
  virtual std::string identify() const = 0;
};

// Derived class
class Rectangle : public Shape {
 public:
  // The base class should be initialized in the constructor's
  // initialization section. What you did was declare a temporary Shape that
  // went away when the function ended.
  // All class data should be set in the initialization section
  Rectangle(int w, int h) : Shape(), width(w), height(h) {}
  double getArea() const override { return (width * height); }

  std::string identify() const override { return "Rectangle"; }

 private:
  int width = 0;
  int height = 0;
};

// A new derived class that should work (a circle **is-a** shape), but doesn't
// with your setup. Circles don't have width and height
class Circle : public Shape {
 public:
  Circle(int r) : Shape(), radius(r) {}
  double getArea() const override { return 2 * 3.14 * radius * radius; }
  std::string identify() const override { return "Circle"; }

 private:
  int radius = 0;
};

// Subjective, I moved the function below the class definitions and added a body
void foo(Shape &s) {
  std::cout << "A " << s.identify() << " with area " << s.getArea() << ".\n";
}

int main(void) {
  Rectangle rect(5, 3);
  foo(rect);

  Circle circ(4);
  foo(circ);

  return 0;
}

输出:

A Rectangle with area 15
A Circle with area 100.48

如果我移除所有虚拟的东西,很多东西就会停止工作。现在我必须提供shape函数的实现。这在逻辑上没有多大意义。虽然我可以将派生对象传递给foo(),但它们会被切片,而填充器shape数据会被打印出来。

 类似资料:
  • 我创建了Angular2 Typescript项目。我有很多表格,所以我想有一个类似基本组件的东西。 这是我的基本组件: 现在有我的子组件。我想从http获取所有项目,然后将其分配给基类 知道如何从订阅方法访问基字段吗?

  • 首先,我确实在谷歌上做了一个快速搜索,没有一个解释我拍摄的目的。 我的问题是如何在成员函数中访问该消息,例如(中的虚函数)?父类中没有定义或类似的函数,如果调用恰好是我要重写的函数,那么调用该函数是非常没用的。 我使用的是Visual Studio Community 2015,因此编译器特定的方法是可以的,但我更喜欢可移植的解决方案。

  • 问题内容: 为什么在C#中,不允许派生类具有比其基类更大的可访问性。 例如,这将产生错误:可访问性不一致:与“ DerivedClass”类相比,基类“ BaseClass”的访问性较差 以及为什么在Java中允许它。 问题答案: 更新 :这个问题是我在2012年11月13日发布的博客的主题。感谢您提出的好问题! 为什么在C#中,不允许派生类具有比其基类更大的可访问性? 除了其他好的答案之外,请考

  • 从已有的对象类型出发建立一种新的对象类型,使它部分或全部继承原对象的特点和功能,这是面向对象设计方法中的基本特性之一。继承不仅简化了程序设计方法,显著提高了软件的重用性,而且还使得软件更加容易维护。派生则是继承的直接产物,它通过继承已有的一个或多个类来产生一个新的类,通过派生可以创建一种类族。   继承 基本概念 在定义一个类A时,若它使用了一个已定义类B的部分或全部成员,则称类A继承了类B,并称

  • 下面是一个人为的例子:(实际代码中使用的命名方案太令人困惑) 我有一个班主任,他是第三方图书馆的一部分,不可更改。我也有一些课程延伸到父亲;比如儿子。祖父有一个类似这样的构造函数: 这个构造函数中实际发生的事情并不重要。重要的是,它所做的任何事情都必须由所有派生类完成,因此对的调用是每个派生类构造函数的第一行。这里的含义是,祖父的所有后代的构造函数,无论距离有多远,都必须始终调用super(或调用

  • 和构造函数类似,析构函数也不能被继承。与构造函数不同的是,在派生类的析构函数中不用显式地调用基类的析构函数,因为每个类只有一个析构函数,编译器知道如何选择,无需程序员干涉。 另外析构函数的执行顺序和构造函数的执行顺序也刚好相反: 创建派生类对象时,构造函数的执行顺序和继承顺序相同,即先执行基类构造函数,再执行派生类构造函数。 而销毁派生类对象时,析构函数的执行顺序和继承顺序相反,即先执行派生类析构