【发布时间】:2020-10-07 14:54:04
【问题描述】:
我有一个Derived 类,其构造函数必须填充struct 的字段,该字段作为参数传递给Base 类的构造函数。我希望能够命名我正在填充的结构的字段,以保持我的代码面向未来(即:抵抗MyStruct 成员的添加和/或重新排序)。
注意struct MyStruct 有默认值,因此不能直接在初始化列表中使用命名字段进行初始化(例如:Base({.a = a, .b = b}) 不起作用)。另外,在我的例子中,Base 的复制构造函数被删除了。另外,我使用的是 C++ 11。
我想出的解决方案是使用placement new运算符在this指向的内存上手动调用Base类的构造函数。为了实现这一点,我还必须在我的Base 类中添加一个protected 默认构造函数。这种方法是否有任何可能的缺点和/或有人可以提出更好的方法吗?
#include <iostream>
struct MyStruct
{
int a = 0;
int b = 1;
};
class Base
{
public:
Base(MyStruct str){
std::cout << "a: " << str.a << ", b: " << str.b << "\n";
}
Base(Base&&) = delete; // no copy constructor
protected:
Base(){ // dummy, does exactly nothing.
// it only exists to be called by
// the derived class's constructor
}
private:
int amember;
};
class Derived : public Base
{
public:
Derived(int a, int b)
{
MyStruct str;
str.a = a;
str.b = b;
new (this) Base(str);
}
private:
int anothermember;
};
int main()
{
MyStruct str;
str.a = 10;
str.b = 20;
Base b(str);
Derived d(10, 20);
return 0;
}
编辑:补充提到 Base 不能被复制,明确指出 Base::Base() 什么都不做。
【问题讨论】:
-
您在寻找named-arguments吗?
-
在我想出这个使用 struct 的解决方案之前,我一直在研究这个问题。我认为命名参数是 C++ 真正需要的一个特性,并且提供的解决方案比我希望的要复杂。
-
第二段似乎没有意义。指定的初始化器将在 C++20 中添加,
Base({.a = a, .b = b})将是正确的。一些编译器已经支持。 -
是的,c++20 有望带来这一点,但问题被标记为 c++11。是不是提到“
Base不能被复制”你认为没有意义?我会改写。我的意思是,在这种情况下,Base类有一个已删除的复制构造函数,在@NathanOliver 的原始答案(现已编辑)假设复制构造函数可用之后,我必须澄清这一点。我现在再澄清一下。 -
Base的拷贝构造函数与此无关