C++:如何强制派生类设置基成员变量?
Posted
技术标签:
【中文标题】C++:如何强制派生类设置基成员变量?【英文标题】:C++: How to enforce derived class to set base member variables? 【发布时间】:2013-10-08 23:12:29 【问题描述】:我有一个带有成员变量的基类(最好是private
),我需要强制派生类使用基于其实现的值对其进行初始化;很像纯虚函数。
为了澄清,我想在 Base 中声明一个成员,让派生类对其进行初始化,如果不这样做,则会出现编译器错误。在下面的代码中,我将Base
的默认构造函数声明为protected
。然后将Derived
的默认构造函数声明为private
。
class Base
private:
int _size;
protected:
Base()
/* pure virtual methods */
public:
Base(int size) : _size(size) // must enforce derived to call this.
virtual ~Base()
/* more pure virtual methods */
;
class Derived : public Base
private:
Derived()
public:
Derived(int size) : Base(size)
//Base::Base(size);
;
int main()
Derived* d1 = new Derived(); // throws an error as needed:
// "Cannot access private member declared in class 'Derived'"
Derived* d2 = new Derived; // throws an error as needed:
// "Cannot access private member declared in class 'Derived'"
Derived* d3 = new Derived(5); // works as needed
return 0;
上面代码的问题是,如果Derived
的另一个定义没有隐藏默认构造函数。我仍然遇到未初始化的Base::_size
。
我不知道除了继承之外是否还有其他方法可以解决这个问题,因为我仍然需要派生类来为Base
中声明的几个方法实现它们自己的行为。
任何指针表示赞赏。
【问题讨论】:
Base::Base(size);
这可能不是你认为的那样。如果要调用基类ctor,请使用mem-initializer-list:Derived(int size) : Base(size) /*...*/
好的,谢谢。刚刚编辑了代码。
拥有带参数的构造函数会自动移除默认构造函数。你不需要做一个私人的。
@NeilKirk 是的,但它不强制用户使用参数化 ctor。如果类没有显式定义默认构造函数,则编译器会自动创建它。对吗?
@mbadawi23 如果存在用户声明的 ctor,则将不隐式声明默认 ctor。
【参考方案1】:
在混淆了调用基类ctor和默认ctor之后,也许解决方案就是在Base
中没有默认ctor?
class Base
private:
int _size;
public:
// no default ctor
Base(int size) : _size(size) // must enforce derived to call this.
virtual ~Base()
/* more pure virtual methods */
;
class Derived : public Base
public:
// no default ctor
Derived(int size) : Base(size)
// examplary default ctor:
//Derived() : Base(42)
;
int main()
Derived d1; // error: no default ctor
Derived* d2 = new Derived; // same, but why use the free store?
Derived d3(5); // works as needed
Derived* d4 = new Derived(5); // same, but why use the free store?
return 0;
要明确表示没有默认 ctor,可以使用
class Base
/* ... */
Base() = delete;
/* ... */
;
【讨论】:
【参考方案2】:使用构造函数
类 Base1 受保护: Base1(int forward) thingYouWantToHide = 转发; 私人的: int thingYouWantToHide; ;
class Derived1: public Base1
public:
Derived1(): Base1(5)
;
class Base2
private:
int value;
protected:
Base2()
value = calledToGet();
virtual int calledToGet() = 0;
virtual ~Base2() //shut compiler warnings up
;
class Derived2: public Base2
virtual int calledToGet()
return 5;
;
int main(int,char**)
Derived1 a;
Derived2 b;
return 0;
您可能认为 Derived2 会起作用,但请记住,Derived2 直到 Base2 才被构造,所以当 Base2 被构造时 virtual 是一个未定义的引用。
你应该使用第一种情况,类型特征如果它是一个常量(静态常量)或类型的基础。
【讨论】:
我不确定我是否理解正确,使用您的Base2
和Derived2
我收到未解决的Base2::calledToGet()
的链接器错误。自然是因为编译器希望Base2
完整。您能否详细说明您提出的解决方案。以上是关于C++:如何强制派生类设置基成员变量?的主要内容,如果未能解决你的问题,请参考以下文章
当我在 C++ 中派生一个类时,它是不是会创建一个基类对象并将其作为我的成员变量存储在派生类中?