C++ 如何使用子类中的自定义虚函数初始化基成员变量
StructComponent类的构造函数根据info的传入对象的类型,采用不同的逻辑初始化其成员变量。这里我使用casting将pass-in参数转换为right子类对象C++ 如何使用子类中的自定义虚函数初始化基成员变量,c++,design-patterns,C++,Design Patterns,StructComponent类的构造函数根据info的传入对象的类型,采用不同的逻辑初始化其成员变量。这里我使用casting将pass-in参数转换为right子类对象 class StructComponent { public: StructComponent(const ClassA& info) { if (info.getType() == CLASS_B) { const ClassC& cl
class StructComponent
{
public:
StructComponent(const ClassA& info)
{
if (info.getType() == CLASS_B)
{
const ClassC& classC = dynamic_cast<const ClassC&> info;
...
apply a different logic for ClassB and init member accordingly
} else if (info.getType() == CLASS_C) {
apply a different logic for others
...
} else {
apply default
}
}
}
class ClassA
{
public:
ClassA(...)
{
m_shp = CreateStructComponent();
}
virtual boost::shared_ptr<StructComponent> CreateStructComponent()
{
return boost::shared_ptr<StructComponent> (new StructComponent(*this));
}
...
int getType() const { return CLASS_A; }
protected:
boost::shared_ptr<StructComponent> m_shp;
}
class ClassB : public ClassA
{
public:
...
virtual boost::shared_ptr<StructComponent> CreateStructComponent()
{
return boost::shared_ptr<StructComponent> (new StructComponent(*this));
}
...
int getType() const { return CLASS_B; }
}
class ClassC : public ClassA
{
public:
...
virtual boost::shared_ptr<StructComponent> CreateStructComponent()
{
return boost::shared_ptr<StructComponent> (new StructComponent(*this));
}
...
int getType() const { return CLASS_C; }
}
类结构组件
{
公众:
结构组件(const ClassA和info)
{
if(info.getType()==CLASS_B)
{
const ClassC&ClassC=动态演员信息;
...
相应地为ClassB和init成员应用不同的逻辑
}else if(info.getType()==CLASS_C){
为其他人应用不同的逻辑
...
}否则{
应用默认值
}
}
}
甲级
{
公众:
A类(…)
{
m_shp=CreateStructComponent();
}
虚拟boost::shared_ptr CreateStructComponent()
{
返回boost::shared_ptr(新结构组件(*this));
}
...
int getType()常量{return CLASS_A;}
受保护的:
boost::共享_ptr m_shp;
}
B类:公共A类
{
公众:
...
虚拟boost::shared_ptr CreateStructComponent()
{
返回boost::shared_ptr(新结构组件(*this));
}
...
int getType()常量{return CLASS_B;}
}
C类:公共A类
{
公众:
...
虚拟boost::shared_ptr CreateStructComponent()
{
返回boost::shared_ptr(新结构组件(*this));
}
...
int getType()常量{return CLASS_C;}
}
Q1>忽略潜在设计问题的代码是否正确
Q2>假设ClassA的所有子类都具有函数CreateStructComponent的相同实现体。
有没有一种方法可以节省空间,不重复执行以下相同的代码:
return boost::shared_ptr<StructComponent> (new StructComponent(*this));
returnboost::shared_ptr(新结构组件(*this));
Q3>我可以使用更好的设计吗?例如,有没有一种方法可以让我忽略
结构组件 在执行类
A
的构造函数期间,对象的类型为A
。因此,将始终调用基本实现。因此,您可以省去重新键入实现的麻烦
此代码设计不正确;错误设计的代码永远都是不正确的,至少在“正确”这个词的通常意义上是如此
没有理由,如果C++规则对你不适用,为什么你应该使用构造函数来初始化。只需将其设置为一个方法,调用thing
Initialize
,您就可以从Initialize
调用所需的任何虚拟方法,产生您似乎期望的效果。在执行类a
的构造函数期间,对象的类型是a
。因此,将始终调用基本实现。因此,您可以省去重新键入实现的麻烦
此代码设计不正确;错误设计的代码永远都是不正确的,至少在“正确”这个词的通常意义上是如此
没有理由,如果C++规则对你不适用,为什么你应该使用构造函数来初始化。只要把它变成一个方法,调用东西Initialize
,你就可以从Initialize
中调用你想要的任何虚拟方法,产生你似乎期望的效果。1)不,这不正确,至少它没有达到你可能期望的效果。它在ClassA
的构造函数中调用一个虚拟函数,它总是调用ClassA::CreateStructComponent()
而不是调用派生类中的重写函数,因为当ClassA
构造函数运行时,动态类型是ClassA
。出于同样的原因,在StructComponent
的构造函数中,getType()
调用将始终解析为ClassA::getType()
2) 有很多方法可以解决这个问题。您可以将代码放在模板中,因此它取决于类型,或者您也可以通过在不同的位置执行初始化来消除复制代码的需要
3) 为什么不简单地给StructComponent
重载构造函数,一个取ClassB
,一个取ClassC
,另一个取ClassA
同样,一个更好的解决方案可能是去掉StructComponent
构造函数,让ClassA
、ClassB
、或ClassC
显式地进行初始化,以便每种类型都按照自己的方式进行初始化。如果初始化取决于创建它的类型,则初始化不属于StructComponent
构造函数。目前,您有一个循环依赖项,StructComponent
需要了解使用它的所有类型,而使用它的所有类型都需要了解StructComponent
。这通常是设计问题的一个标志,所有的类都是紧密耦合的。如果StrictComponent
对其他类型一无所知,那就更好了
无论如何,这里有一个可能的解决方案,展示了一种在不复制代码的情况下将正确类型传递给StructComponent
的方法,但我认为这不是一个好的设计。请注意,Structcomponent
构造函数被传递为NULL,因此它可以根据类型执行不同的操作,但是无法访问它传递的对象
class StructComponent
{
public:
explicit StructComponent(const ClassA*)
{ /* something */ }
explicit StructComponent(const ClassB*)
{ /* something else */ }
explicit StructComponent(const ClassC*)
{ /* something completely different */ }
};
class Base
{
protected:
template<typename T>
explicit
Base(const T*)
: m_shp( boost::make_shared<StructComponent>((T*)NULL) )
{ }
boost::shared_ptr<StructComponent> m_shp;
};
class ClassA : virtual public Base
{
public:
ClassA() : Base(this) { }
};
class ClassB : public ClassA
{
public:
ClassB() : Base(this) { }
};
class ClassC : public ClassA
{
public:
ClassC() : Base(this) { }
};
这里还有另一个选择,这次没有循环依赖,将不同的初始化代码移到它所属的位置:
struct StructComponent
{
StructComponent() { /* minimum init */ }
};
class ClassA
{
public:
ClassA() : m_shp( createA() ) { }
protected:
struct no_init { };
explicit
ClassA(no_init)
: m_shp()
{ }
boost::shared_ptr<StructComponent> createA()
{
// something
}
boost::shared_ptr<StructComponent> m_shp;
};
class ClassB : public ClassA
{
public:
ClassB()
: ClassA(no_init())
{ m_shp = createB(); }
private:
boost::shared_ptr<StructComponent> createB()
{
// something else
}
};
class ClassC : public ClassA
{
public:
ClassC()
: ClassA(no_init())
{ m_shp = createC(); }
private:
boost::shared_ptr<StructComponent> createC()
{
// something completely different
}
};
struct结构组件
{
StructComponent(){/*最小初始值*/}
};
甲级
{
公众:
ClassA():m_shp(createA()){}
受保护的:
结构no_init{};
明确的
A类(无初始)
:m_shp()
{ }
boost::shared_ptr createA()
{
//某物
struct StructComponent
{
StructComponent() { /* minimum init */ }
};
class ClassA
{
public:
ClassA() : m_shp( createA() ) { }
protected:
struct no_init { };
explicit
ClassA(no_init)
: m_shp()
{ }
boost::shared_ptr<StructComponent> createA()
{
// something
}
boost::shared_ptr<StructComponent> m_shp;
};
class ClassB : public ClassA
{
public:
ClassB()
: ClassA(no_init())
{ m_shp = createB(); }
private:
boost::shared_ptr<StructComponent> createB()
{
// something else
}
};
class ClassC : public ClassA
{
public:
ClassC()
: ClassA(no_init())
{ m_shp = createC(); }
private:
boost::shared_ptr<StructComponent> createC()
{
// something completely different
}
};