为具有多重继承的一个类型设置默认构造函数
Setting a default constructor for one type with multiple inheritance
我有两个类,Base
和Derived
。Derived
继承了Base
的所有构造函数。此外,我有一个模板类Printer<T>
,它包含对T
类型对象的引用,并有一个方法print()
,以某种方式打印对象。下面是一个简单的例子。
class Base {
public:
Base(int x) : x(x) {}
int x;
};
template<typename T>
class Printer {
public:
const T& object;
Printer(const T& object) : object(object) {}
void print() {
cout << object << endl;
}
};
class Derived : public Base {
public:
using Base::Base;
};
std::ostream& operator<<(std::ostream& out, const Derived& d) {
return out << d.x;
}
int main() {
Derived d(1);
Printer<Derived>(d).print();
}
现在我想避免直接使用Printer
并允许这样的语法:Derived d(1); d.print();
。因此,我试图从Printer<Derived>
继承Derived
。
class Derived : public Base, public Printer<Derived> {
public:
typedef Printer<Derived> MyPrinter;
using Base::Base;
Derived() : MyPrinter(*this) {}
};
现在我有一个问题:Base
构造函数对Printer
一无所知,因此无法以任何方式初始化它。我也不能在这里使用构造函数委托,因为在Derived
中使用的构造函数实际上是从Base
继承的。
我能以某种方式使Derived
的默认构造函数由任何其他构造函数委托,甚至继承的构造函数吗?或者在多重继承中有一些其他的模式来初始化第二个基?
还有一件事使一切变得更糟,那就是我不能访问Base
的代码,只能按原样使用它。
关于Remy Lebeau的回答:Base
可以有多个我不知道的构造函数(它也是一个模板类),所以我不能实现所有的构造函数,必须使用using Base::Base
的习惯用法。
关于krzaq的回答:Printer
实际上也有很多方法,不仅仅是print()
,所以实现转发器类是一个麻烦,我尽量避免它。
如果您需要的只是访问Printer<Derived>
的Derived
实例,那么您可以简单地将其cast down:
template<typename T>
class Printer {
public:
const T& object;
Printer() : object(static_cast<T&>(*this)) {}
void print() {
cout << object << endl;
}
};
现场演示
或完全取消引用,使您的类符合EBO:
template<typename T>
class Printer {
public:
void print() {
cout << static_cast<T&>(*this) << endl;
}
};
现场演示
如果你不能/不想触摸Printer
,我将创建一个单独的模板PrinterForwarder
转发print()
调用到正确的打印机:
template<typename T>
class PrinterForwarder
{
public:
void print() {
Printer<T>(static_cast<T&>(*this)).print();
}
};
class Derived : public Base, public PrinterForwarder<Derived> {
public:
using Base::Base;
};
现场演示
现在我有一个问题:基构造函数对Printer一无所知,因此无法以任何方式初始化它。
要做你正在尝试的事情,你将不能再使用using Base::Base
语句了。您必须更明确地了解Derived
实现的构造函数,以便它们可以根据需要初始化Printer
基类,例如:
class Derived : public Base, public Printer<Derived> {
public:
typedef Printer<Derived> MyPrinter;
Derived() : Base(0), MyPrinter(*this) {}
Derived(int x) : Base(x), MyPrinter(*this) {}
};
或:
class Derived : public Base, public Printer<Derived> {
public:
typedef Printer<Derived> MyPrinter;
Derived() : Derived(0) {}
Derived(int x) : Base(x), MyPrinter(*this) {}
};
您可以创建一个可变的模板捕获所有构造函数,它将参数传递给Base并根据需要构造Printer,如下所示
class Derived: ... {
template<typename... Args>
Derived(Args&&... args): Base(std::forward<Args>(args)...), Printer(*this) {}
}
我发现了一个非常简单的解决方案。让我们在Printer
中存储一个指向T
的指针,而不是引用。
template<typename T>
class Printer {
public:
const T* objectPtr;
Printer() : objectPtr(nullptr) {}
Printer(const T& object) : objectPtr(&object) {}
void print() {
if (objectPtr) {
cout << *objectPtr << endl;
} else {
cout << static_cast<const T&>(*this) << endl;
}
}
};
它看起来不是真的安全,但使Printer()
ctor私有似乎使交易。
- 我想将一个对T类型的非常量左值引用绑定到一个T类型的临时值
- 检查一个类型是否直接派生自"enable if"上下文中的另一个类型(是其子类型)
- 给定一个类型,如何派生一个泛型更广泛的类型(例如,用于溢出安全求和)?
- 更改可变参数模板中的最后一个类型
- 如何构造一个类型特征,可以判断一个类型的私有方法是否可以在另一个类型的构造函数中调用?
- 有没有办法同时将一个类型分配给C++中的多个模板?
- C++:可以模板化一个类型名称吗
- 有没有一种方法可以使用SFINAE来检测一个类型是否实现了给定的抽象基类
- 给定一个类型为 Container:<T>:Iterator 的函数参数,如何为某些类型的 T 实现特定的重载?
- 期望一个类型,得到一个模板
- 初始化一个类型向量的巨大向量<int>
- 我可以使用预处理器将一个类型声明替换为另一个类型声明吗?
- 具有多种类型的类数组?如何访问数组中的一个类型
- Opencv C++ 声明一个类型为 uint8 的矩阵
- 模板参数列表中只有一个类型名称是什么意思?
- C++模板部分特化:为什么我无法匹配可变参数模板中的最后一个类型
- 为什么我们有一个类型不匹配
- 在函数模板中将一个类型名映射到另一个类型名
- 创建一个类型bool的向量,其中所有值均可初始化为true
- 在C API中定义了一个类型,如何将其与命名空间中的C++类相关联