C++:为啥我的 DerivedClass 的构造函数无法访问 BaseClass 的受保护字段?

Posted

技术标签:

【中文标题】C++:为啥我的 DerivedClass 的构造函数无法访问 BaseClass 的受保护字段?【英文标题】:C++: Why does my DerivedClass's constructor not have access to the BaseClass's protected field?C++:为什么我的 DerivedClass 的构造函数无法访问 BaseClass 的受保护字段? 【发布时间】:2011-03-20 04:37:37 【问题描述】:

我有一个构造函数试图初始化基类中的一个字段。编译器抱怨。该字段是受保护的,因此派生类应该可以访问。

//The base class: 

class BaseClass



public:

    BaseClass(std::string);
    BaseClass(const BaseClass& orig);
    virtual ~BaseClass();
    const std::string GetData() const;
    void SetData(const std::string& data);
protected:

    BaseClass();
    std::string m_data;

;

BaseClass::BaseClass(const std::string data) : m_data(data)  

BaseClass::BaseClass()   

BaseClass::BaseClass(const BaseClass& orig)  

BaseClass::~BaseClass()  

void BaseClass::SetData(const std::string& data)

    m_data = data;


const std::string BaseClass::GetData() const

    return m_data;



//The derived class: 


class DerivedClass : public BaseClass


public:

    DerivedClass(std::string data);
    DerivedClass(const DerivedClass& orig);
    virtual ~DerivedClass();
private:

;

DerivedClass::DerivedClass(std::string data) : m_data(data)   //ERROR HERE

DerivedClass::DerivedClass(const DerivedClass& orig)  

DerivedClass::~DerivedClass()  

//编译错误

DerivedClass.cpp:3:错误:“DerivedClass”类没有任何名为“m_data”的字段

非常感谢任何帮助。提前谢谢你。

【问题讨论】:

谢谢大家。这真的很有帮助! 【参考方案1】:

您不能在派生类构造函数中初始化 m_data,而是将其作为参数传递给基类构造函数。

即:DerivedClass::DerivedClass(std::string data) : BaseClass(data)

【讨论】:

你不知道这有多大帮助【参考方案2】:

在初始化列表中,您可以只为同一类的属性设置值。要访问它,您必须在构造函数的主体中属性值:

DerivedClass::DerivedClass(std::string data) m_data = data;

或者,如果复制对象的成本很高,则将 m_data 作为参数传递给父类构造函数:

DerivedClass::DerivedClass(std::string data) : BaseClass(data)

提示:将您的数据作为引用传递以防止复制构造函数。

在此处查看更多信息:order of initialization of C++ constructors。

【讨论】:

不鼓励在构造函数的主体中分配成员,所以我最多将其放在脚注中。此外,现在该字符串应该是 std::move()d 到成员或基类中,以避免无意义的复制。【参考方案3】:

你不是在“访问”m_data——你是在初始化它。但是,它已经在基类的 ctor 中初始化了。如果要更改它的值,请在 ctor 的正文中分配给它:

DerivedClass::DerivedClass(std::string data) 

   m_data = data;

【讨论】:

当然,他们可以这样做,但他们可能不应该也不会真的想要这样做!不鼓励在构造函数的主体中分配成员,如果它是基类的成员,我认为应该特别强调这一点!这将浪费资源分配一个在不久之后更改的值,在基类的初始化列表和派生类的构造函数主体之间引入一个中间状态,等等。最好避免。【参考方案4】:

需要调用基类构造函数如下:

DerivedClass::DerivedClass(std::string data) : BaseClass(data) 

每个类都应该负责初始化它的成员。

【讨论】:

【参考方案5】:

初始化器列表只能用于初始化相关类型所拥有的字段。在初始化列表中初始化基类字段是不合法的,这就是您收到此错误的原因。该字段可在 DerivedClass 内以其他方式访问

【讨论】:

【参考方案6】:

您的派生类构造函数确实可以访问,但您不能在初始化列表中分配给它。将构造函数更改为:

DerivedClass::DerivedClass(const std::string& data)
 : BaseClass(data)

或者,如果没有合适的基类构造函数可用并且您不能添加一个,您可以将构造函数更改为:

DerivedClass::DerivedClass(const std::string& data)

    m_data = data;

【讨论】:

以上是关于C++:为啥我的 DerivedClass 的构造函数无法访问 BaseClass 的受保护字段?的主要内容,如果未能解决你的问题,请参考以下文章

为啥我不能在 C# 中使用基本构造函数 [重复]

为啥 C++ 不能用“超类”类型的右值初始化“派生类”类型的变量?

为啥在 C++ 中调用原始类型的构造函数是合法的?

为啥我们需要一个默认构造函数来在 C++ 中通过引用传递一个对象?

为啥 C++ 映射类型参数在使用 [] 时需要一个空的构造函数?

为啥我不能在 C++ 中用 new 调用参数化构造函数?