C++ 继承:我必须在派生类中重复父属性吗?

Posted

技术标签:

【中文标题】C++ 继承:我必须在派生类中重复父属性吗?【英文标题】:C++ Inheritance: Do I have to repeat parent attributes in derived classes? 【发布时间】:2018-05-24 19:29:44 【问题描述】:

如果我将我的类分成头文件/实现文件,是否可以在不需要在子类中重新声明继承属性的情况下进行继承?

让我用一个例子来澄清一下。为什么允许这样做(取自here):

#include <iostream>

using namespace std;

// Base class
class Shape 
   public:
      void setWidth(int w) 
         width = w;
      
      void setHeight(int h) 
         height = h;
      

   protected:
      int width;
      int height;
;

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

int main(void) 
   Rectangle Rect;

   Rect.setWidth(5);
   Rect.setHeight(7);

   // Print the area of the object.
   cout << "Total area: " << Rect.getArea() << endl;

   return 0;

但这不是(尝试编译here):

#include <string>
#include <iostream>

// HEADER FILE
class Person    
public:
    virtual void speak() = 0;

protected:
    std::string name;
    std::string surname;
;

class Programmer : public Person 
public:
    Programmer(std::string, std::string);
;

// CPP FILE
Programmer::Programmer(std::string name, std::string surname) : 
    name(name), 
    surname(surname) 


void Programmer::speak()
    std::cout << "My name is " + name + " " + surname + " and I like to code!";

【问题讨论】:

您没有声明 Programmer 来实现名为 speak 的函数 - 在某些情况下您不会为类中的 virtual 函数创建覆盖(这通常是适用于任何 OOP 语言) @UnholySheep 但是属性namesurname 呢?我收到关于 Programmer 的错误,也没有这些错误。 那是因为它们受到保护。导致错误的完全不同的原因。 【参考方案1】:

我不确定什么是令人困惑的。成员初始化器列表仅允许指定基类或此类的直接成员。因此,您的第二个示例未编译。

同时,派生类可以访问其基类的publicprotected 成员,所以这就是第一个示例可以的原因。

一个有趣的观察是以下代码将编译:

Programmer::Programmer(std::string name_, std::string surname_) 
    name = name_;
    surname = surname_;

注意,这意味着namesurname 将首先被默认初始化(为空字符串),然后它们将被分配给Programmer 构造函数中传递的值。这是效率损失,在某些情况下可能非常明显。

惯用地解决这个问题的正确方法是购买给Person一个接受两个字符串参数并初始化成员的构造函数,然后从Programmer构造函数调用这个构造函数。

【讨论】:

令我困惑的是getArea()怎么能引用widthheight(它们是Shape中的protected),但我不能以同样的方式引用namesurnameProgrammer 构造函数中。 @LukeCollins 您不是“以相同的方式”指代它们 - 如果您将分配放在构造函数主体中,它的工作方式与您的第一个示例相同。成员初始化器列表不同。 @LukeCollins 答案很简单——因为这是 C++ 的设计方式。初始化成员是类构造函数的责任(这是重点!),但派生类可以访问这些成员。 现在我明白你的意思了。因此,将它们放入体内是解决方案。谢谢。【参考方案2】:

Programmer 构造函数中,在初始化列表中初始化的变量只能是直接来自该类或基类构造函数的变量。

但是在成员函数/构造函数的主体中可以使用继承的变量,如果它们实际上是publicprotected

【讨论】:

以上是关于C++ 继承:我必须在派生类中重复父属性吗?的主要内容,如果未能解决你的问题,请参考以下文章

在 C++ 继承中,当指向基类的指针对象指向派生类时,不调用派生类析构函数

如何访问派生类中的私有集属性[重复]

继承与派生

C++之继承与派生

继承与派生

QML:在派生类中使属性只读