我有一个班级(名字为例):
class Animal
{
public:
// some virtual methods
};
还有一些子类。
class Dog : public Animal
{
public:
Dog(Map&);
// methods - using m_Map
private:
Map& m_Map;
};
class Elephant : public Animal
{
public:
Elephant(Map&);
// methods - using m_Map
private:
Map& m_Map;
};
如您所见,在创建Dog和Elephant对象时,必须提供Map引用,并且这些类使用它。动物(狗,大象,老鼠,猫等等)有很多类似的子类 - 都使用Map对象。
Animal的所有子类都使用Map对象,我在考虑将它作为受保护成员添加到Animal类是否是个好主意,例如:
class Animal
{
public:
Animal(Map&);
// some virtual methods
protected:
Map& m_Map;
};
class Dog : public Animal
{
public:
Dog(Map& map) : Animal(map);
// methods - using Animal::m_Map
};
class Elephant : public Animal
{
public:
Elephant(Map& map) : Animal(map);
// methods - using Animal::m_Map
};
但是,Animal类永远不会使用Map对象,所以对我来说,在这里存储它有点不自然 - 仅用于子类的使用。
另一方面,Animal的所有子类都将使用Map对象 - 因此最好在Animal类中指明它。而且当我在所有子类中将其定义为成员时,我也感觉代码是重复的。
你怎么看? Map对象是应该在所有子类中定义为成员,还是仅在Animal类中定义?
答案 0 :(得分:2)
这取决于动物和地图之间的语义联系。
由于您使用的是C ++,因此可以使用多重继承。
首先,实现MapWrapper
类:
class MapWrapper {
private:
Map *theMap;
public:
...
};
然后像这样构建你的动物:
class Dog : public Animal, private MapWrapper {
};
请注意,private
继承不是泛化/专门化,只是实现某种强大组合的技巧。
另一种可能性是在Animal
和Dog
之间引入中间类。 Animal
可能是纯粹的抽象类或契约,因此出于实用目的而修改它可能是不公平的。只需介绍AnimalMap
:
class AnimalMap : public Animal {
// everything for the map
};
class Dog : public AnimalMap {
};
答案 1 :(得分:0)
如果基类型的所有派生类型都需要变量或函数,那么该变量或函数应该是基类型的一部分。这是继承的前提 - 以逻辑和系统的方式重复使用代码。
你提到你正在努力解决Animal对象永远不会真正使用Map的事实。您是否考虑过将Animal作为抽象类的类型层次结构的设计?这意味着Animal永远不会被实例化。在给定的例子中,这在概念上是有意义的 - 没有动物是动物;动物的类别包括许多其他更具体的概念,如狗或猫。
我建议这个实现适合你的例子并解决你的哲学难题。
答案 2 :(得分:0)
map对象只能在动物类中定义。为什么因为你继承了所有子类的动物类属性。
这是一个优势,您可以为动物类创建对象,并且您可以访问地图,直到您在动物类中没有任何纯虚拟方法
当谈到一个对象的内存大小时,无论是在基类还是派生类中,你持有地图都没有区别。派生对象的大小只相同
class animal
{
public:
int animal_id;
int animal_age;
};
class dog :public animal
{
public:
int dog_type_id;
};
int main()
{
dog d1;
animal a1;
cout<<"sizeof d1:"<<sizeof(d1)<<endl;
cout<<"sizeof a1:"<<sizeof(a1)<<endl;
return 0;
}