请考虑此类层次结构:
#include <iostream>
struct Base
{
Base(int arg1, int arg2, int arg3, int arg4)
{
std::cout << "Base::Base:" << arg1 << "," << arg2 << "," << arg3 << "," << arg4 << std::endl;
}
void BaseDoWork()
{
std::cout << "Base::BaseDoWork" << std::endl;
}
};
struct Derived1:public Base
{
Derived1(int arg1, int arg2, int arg3, int arg4):Base(arg1, arg2, arg3, arg4){}
void DerivedDoWork()
{
BaseDoWork();
}
};
struct Derived2:public Derived1
{
Derived2(int arg1, int arg2, int arg3, int arg4):Derived1(arg1, arg2, arg3, arg4){}
};
int main(int argc, char *argv[])
{
Derived2 myDerived2(1,2,3,4);
myDerived2.DerivedDoWork();
return 0;
}
类Derived1具有比我想要的更多耦合:它必须知道如何构造“Base”类。在深层次结构中,这意味着将“Base”类构造函数的参数一直传播到类层次结构中。对“Base”类构造函数的更改需要更改所有派生类。
我对这个类层次结构的目标是:
Derived1需要基类中的BaseDoWork()方法,但不需要知道如何构造基类。
Derived2知道如何构建“基础”类。
理想情况下,我想让Derived1成为一个模板,接受任何具有可访问的“BaseDoWork()”方法的基类,如下所示:
template <T> struct Derived1:public T
{
void DerivedDoWork()
{
BaseDoWork();
}
};
但是,如果我将上述模板实例化为Derived1<Base>
,我无法在不向Derived1添加“Base”构造函数参数知识的情况下看到如何构造“Base”类。
答案 0 :(得分:1)
假设这是真正的层次结构,如果Derived1
是Base
派生类,则必须知道如何构建父类(Base
)。
据我所知,也许我错了,如果Derived1
不是真正的Base
派生(子)类,只需要知道它的界面,就没有必要知道如何构造一个Base
实例。因此,您可以按如下方式定义Derived1:
struct Derived1
{
Derived1(int arg1, int arg2, int arg3, int arg4)
{}
.....
};
只有Base
派生类需要知道如何构建Base
:
struct Derived2 : public Base
{
Derived2(int arg1, int arg2, int arg3, int arg4) :
Base(arg1, arg2, arg3, arg4)
{}
.....
};
现在,如果Derived2
真的是Derived1
孩子,那么必须知道如何创建它的父母。以前的代码变成了:
struct Derived2 : public Base, public Derived1
{
Derived2(int arg1, int arg2, int arg3, int arg4) :
Base(arg1, arg2, arg3, arg4),
Derived1(arg1, arg2, arg3, arg4)
{}
.....
};
如果您必须使用Base::BaseDoWork()
中的Derived1
方法,则可以按如下方式定义类:
struct Base
{
Base(int arg1, int arg2, int arg3, int arg4)
{
std::cout << "Base::Base:" << arg1 << "," << arg2 << "," << arg3 << "," << arg4 << std::endl;
}
virtual void BaseDoWork()
{
std::cout << "Base::BaseDoWork" << std::endl;
}
};
struct Derived1
{
Derived1(int arg1, int arg2, int arg3, int arg4)
{}
template <typename T>
void DerivedDoWork(T & base) // only knows T interface
{
base.BaseDoWork();
}
};
struct Derived2 : public Base, public Derived1
{
Derived2(int arg1, int arg2, int arg3, int arg4) :
Base(arg1, arg2, arg3, arg4),
Derived1(arg1, arg2, arg3, arg4)
{}
virtual void DerivedDoWork()
{
Derived1::DerivedDoWork<Base>(*(static_cast<Base *>(this)));
}
};
Main保持不变。
您可能需要查看此层次结构。
答案 1 :(得分:1)
当您从public
进行Derived1
的{{1}}继承时,结果是Base
已经知道如何构建Derived1
,所以如果您需要{ {1}}不知道如何构建Base
,也许最好不要从Derived1
继承它?相反,将Base
分开作为某种表演者。
考虑一下这段代码,我并不认为这是解决方案,但也许它会让你想到其他想法(类的名称是相同的):
Base