假设有一个带有常量值的基类,一个从基类派生的中间子类,以及一个派生自中间类的最终派生类。
如果我们想在派生类的初始化列表中使用常量,那么如何才能做到这一点?
以下是示例代码:
#include <iostream>
class Base{
protected:
const std::size_t c;
Base() : c(64){}
};
class Intermediate : public Base{
public:
Intermediate(int val){
std::cout << "In Intermediate c is " << c << std::endl; // In Intermediate c is 64
std::cout << "However, val = " << val << std::endl; // However, val = 10
}
};
class Derived : public Intermediate{
public:
Derived(int val) : Intermediate(this->c+val){
std::cout << "In Derived c is " << c << std::endl; // In Derived c is 64
}
};
int main(){
Derived instance(10);
return 0;
}
所需的输出为74,但是在调用Derived类的初始化列表时,c尚未初始化。
我看到的可能解决方案是:
但是,我想保持整体结构不变(初始化列表)而没有构造函数体,所以如何在初始化期间使用基类的const?
答案 0 :(得分:2)
在处理构造函数之前,您已使用此值。
您已使用c
符号作为构造函数的参数,因此您创建了鸡蛋问题。
启用编译器中的-Wall
开关以捕获此类问题
编译器警告你,你正在做一些可疑的事情:
https://wandbox.org/permlink/DIYaSQQ4FQQwsmkO
prog.cc: In constructor 'Derived::Derived(int)':
prog.cc:20:47: warning: '*<unknown>.Derived::<anonymous>.Intermediate::<anonymous>.Base::c' is used uninitialized in this function [-Wuninitialized]
Derived(int val) : Intermediate(this->c+val){
~~~~~~^
正确的修复方法是不使用幻数(在某种程度上ti是这个问题): https://wandbox.org/permlink/1nfa3eXP2XIhgRE8
class Base{
protected:
static const std::size_t cDefaultValue = 64;
const std::size_t c;
Base() : c(cDefaultValue){}
};
class Intermediate : public Base{
public:
Intermediate(int val){
std::cout << "In Intermediate c is " << c << std::endl; // In Intermediate c is 64
std::cout << "However, val = " << val << std::endl; // However, val = 10
}
};
class Derived : public Intermediate{
public:
Derived(int val) : Intermediate(cDefaultValue + val){
std::cout << "In Derived c is " << c << std::endl; // In Derived c is 64
}
};
另一种解决方法是组合。可悲的是,大多数开发人员倾向于过度使用继承,在大多数情况下,组合是更好的选择。
答案 1 :(得分:1)
您只需要一个接受Base访问者的Intermediate中受保护的ctor。然后,您可以在基础上提供任何类型的访问者(=计算),可以由中级使用,因此具有多个后代。您甚至可以通过模板将其设为静态访问者。
{{1}}