据我所知,你不能在C ++中继承构造函数。但是在某些情况下,可能需要看起来像实例化继承类一样,实例化它们的基础:
struct Base {
int i;
int const j;
Base(int i, int j) : i(i), j(j) {}
};
// option 1)
struct Derived1 : Base {
Derived1(int i, int j) : Base(i,j) {}
};
Base* baseFactory() {
return new Derived1(42,47);
}
// option 2)
struct Derived2 : Base {
};
Base* baseFactory() {
Base* b = new Derived2();
b->i = 42;
b->j = 47; // broken!
// alternative could be to implement Base::operator=
return b;
}
请注意,如果派生类不是基类,则可以默认构造。
我认为选项1是通常所做的,但您输入的代码却没有表达任何新内容。选项2打破const
正确性(并阻止您将引用用作成员),因为所有内容都必须是可分配的。
这有什么好办法吗?
编辑:C ++ 11很棒,但不幸的是我需要一个C ++ 03解决方案。
答案 0 :(得分:3)
选项1是C ++ 03中惯用的方式,它需要更多的输入,但这就是语言的方式。选项2甚至不等同,您将无法初始化Derived2
,因为Base
没有默认构造函数,并且隐式声明的默认构造函数的定义Derived2
需要它。
但是超出了语言的技术难度,您正在为两阶段构建进行构建,这绝不是一个好主意,同时也迫使您使用Derived2
动态分配对象。
答案 1 :(得分:2)
还有另一种方法:
// option 3)
struct Derived3 : Base {
Derived3(const Base &b) : Base(b) {}
};
Base* baseFactory3() {
return new Derived3(Base(42,47));
}
如果构建完整的Base对象很昂贵或需要外部资源,这可能不是一个好主意。在这种情况下,您可以创建一个携带Base的构造函数参数的轻量级对象,这样您就可以使用多个BaseArguments构造函数和一个接受BaseArguments的Base构造函数来代替多个Base构造函数。但是我不认为很多人会在大多数情况下考虑这种好风格。
答案 2 :(得分:1)
C ++ 11支持继承的构造函数。
http://en.wikipedia.org/wiki/C%2B%2B11
然而,并非现在支持C ++ 11子集的所有编译器都支持所有功能。
Microsoft Visual C ++ 2010支持几个新的C ++ 0x功能但不支持继承的构造函数,这里有一个列表:http://blogs.msdn.com/b/vcblog/archive/2010/04/06/c-0x-core-language-features-in-vc10-the-table.aspx
GCC支持更多新功能,但不支持继承的构造函数。见http://gcc.gnu.org/projects/cxx0x.html
要使GCC能够使用C ++ 0x功能进行编译,您需要添加-std=c++0x
或-std=gnu++0x
编译参数。
Visual C ++ 2010默认启用这些。
你只需要等待:)
以前版本的标准没有干净的解决方案,因此它是在C ++ 11中引入的,因为它不可能与以前的版本一起使用。 所以,你唯一能做的就是复制你的构造函数并调用基础构造函数。
答案 3 :(得分:1)
这里有一个Builder模式的变体,我一直认为它可能有用,但我实际上没有机会使用它;我想你可以把它称为构造函数模式。 :P
它还提供了一些其他优点,例如不必按特定顺序指定参数:您只需指定您感兴趣的内容以及您想要的任何顺序。
我仍然认为只有当你的类有很多带有不同参数的构造函数时才有理由这样做。否则,这只是一个烦恼。
class Person
{
public:
class Constructor;
};
class Person::Constructor
{
public:
Constructor& name(const std::string&);
Constructor& age(int);
Person* make();
};
Person* pers = Person::Constructor()
.name("Bob Marley").make();
class Employee : public Person
{
public:
class Constructor;
};
class Employee::Constructor : public Person::Constructor
{
public:
Constructor& salary(double);
Employee* make();
};
Employee* emp = Employee::Constructor()
.name("Emilly Smith").age(23).make();
但是,只有当你的类有很多带有大量参数的构造函数并且你想避免必须为这些构造写多个重载时,这才是合理的。否则,这只会增加太多复杂性而没有任何实际好处。
我提到过我不喜欢汉提出的解决方案。这是因为(1)你需要(重新)在子类中声明一些构造函数,以便在工厂类中放置相同数量的函数; (2)它是hacky,意图不明确; (3)你可以将其视为违反依赖注入的行为。