继承的构造函数和附加变量的解决方法
Workaround for inherited constructor and additional variables
我需要一个解决方法或一个很好的解决方案来初始化 base 和 subclass
中的一堆常量 class 变量
问题很简单,我得到了一个baseclass有两个构造函数和subclass
中同样的两个构造函数
class BASE {
int a;
int func(float x) { // just a dummy to show that this function
return (a = (int) x) + 2; // modifies a
}
public:
const int b;
BASE(const int b) : b(b) {} // doesn't use a
BASE(const float x) : a(0), b(func(x)) {}
};
struct SUB: public BASE {
const int c;
const int d;
SUB(const int b) : BASE(b), c(b), d(c + 3) {}
SUB(const float x) : BASE(x), c(b), d(c + 3) {}
};
subclass需要调用BASE的构造函数来初始化BASE的class变量,然后subclass初始化剩余的变量
到目前为止一切顺利,但问题是 SUB 中的两个构造函数除了调用 BASE 中的不同构造函数外完全相同
我想要那样的东西
SUB() : c(b), d(c + 3) {} // BASE() needs to be defined
SUB(const int b) : BASE(b), SUB() {}
SUB(const float x) : BASE(x), SUB() {}
但这行不通,因为 "a call to a delegating constructor shall be the only member-initializer" ...
将所有内容移到初始化列表之外是行不通的,因为它们是 const class 变量
不幸的是,这是语言的规则,如果你有一个 delegating constructor 它必须是初始化列表的唯一部分。
您需要解决该限制,例如通过复制默认构造函数初始化列表:
SUB(const int b) : BASE(b), c(b), d(c + 3) {}
您可以为派生的 class 创建一个 "forwarding constructor":
struct SUB: public BASE {
const int c;
const int d;
template <class... T>
SUB(T&&... a) : BASE(std::forward<T>(a)...), c(b), d(c + 3) {}
};
这将接受任意参数并将它们转发给 BASE
。当然,它只会在使用对 BASE
有效的参数调用时编译,但这适用于所有情况。
如果你 want/need 是超级正确的,你可以使用 SFINAE 来调节构造函数,比如 std::is_constructible<BASE, T&&...>
,但我不会打扰。
我需要一个解决方法或一个很好的解决方案来初始化 base 和 subclass
中的一堆常量 class 变量问题很简单,我得到了一个baseclass有两个构造函数和subclass
中同样的两个构造函数class BASE {
int a;
int func(float x) { // just a dummy to show that this function
return (a = (int) x) + 2; // modifies a
}
public:
const int b;
BASE(const int b) : b(b) {} // doesn't use a
BASE(const float x) : a(0), b(func(x)) {}
};
struct SUB: public BASE {
const int c;
const int d;
SUB(const int b) : BASE(b), c(b), d(c + 3) {}
SUB(const float x) : BASE(x), c(b), d(c + 3) {}
};
subclass需要调用BASE的构造函数来初始化BASE的class变量,然后subclass初始化剩余的变量
到目前为止一切顺利,但问题是 SUB 中的两个构造函数除了调用 BASE 中的不同构造函数外完全相同
我想要那样的东西
SUB() : c(b), d(c + 3) {} // BASE() needs to be defined
SUB(const int b) : BASE(b), SUB() {}
SUB(const float x) : BASE(x), SUB() {}
但这行不通,因为 "a call to a delegating constructor shall be the only member-initializer" ...
将所有内容移到初始化列表之外是行不通的,因为它们是 const class 变量
不幸的是,这是语言的规则,如果你有一个 delegating constructor 它必须是初始化列表的唯一部分。
您需要解决该限制,例如通过复制默认构造函数初始化列表:
SUB(const int b) : BASE(b), c(b), d(c + 3) {}
您可以为派生的 class 创建一个 "forwarding constructor":
struct SUB: public BASE {
const int c;
const int d;
template <class... T>
SUB(T&&... a) : BASE(std::forward<T>(a)...), c(b), d(c + 3) {}
};
这将接受任意参数并将它们转发给 BASE
。当然,它只会在使用对 BASE
有效的参数调用时编译,但这适用于所有情况。
如果你 want/need 是超级正确的,你可以使用 SFINAE 来调节构造函数,比如 std::is_constructible<BASE, T&&...>
,但我不会打扰。