C++ C++;更改派生类中的成员类型

C++ C++;更改派生类中的成员类型,c++,inheritance,overloading,C++,Inheritance,Overloading,我有一个类Base1,它包含一个不同类Base2的对象数组。我希望有一个派生类Derived1,它继承Base1的所有内容,但数组的类型是Derived2(它是Base2的派生类)。例如,类似这样的内容: class Base2{ int a2; }; class Derived2: public Base2{ int b2; }; class Base1{ Base2* list; }; class Derived1: public Bas

我有一个类Base1,它包含一个不同类Base2的对象数组。我希望有一个派生类Derived1,它继承Base1的所有内容,但数组的类型是Derived2(它是Base2的派生类)。例如,类似这样的内容:

class Base2{
        int a2;
};

class Derived2: public Base2{
        int b2;
};

class Base1{
        Base2* list;
};

class Derived1: public Base1{
        Derived2* list;
};
我的理解是,在上面的示例中,Derived1的对象实际上有两个数组:

list

这是我不想要的

其思想是,由于Derived2“是”Base2,因此Base1的所有功能仍应适用于Derived1对象。这会非常脏,但我想我可以删除Derived1构造函数中的Base1::list数组


有人看到解决这个问题的办法吗?这似乎是经常发生的事情,我不能相信没有一个简单的解决办法。使用模板有效吗?我的想法是否定的,因为Base1和Derived1中的所有功能都需要知道它们分别处理Base2和Derived2对象。

当有人将
Derived1
类降级到
Base1
时,您预计会发生什么?在破坏基类后使用
list
时,它将崩溃。最好的办法是继续使用基类的
列表
,并确保列表中只包含
Derived2
类型的对象。如果列表的内容不能从外部修改,那么这将起作用,而且是安全的


是的,我知道还有很多话要说,但让我们一步一步地说。

一般情况下,你试图做的事情似乎很危险,但我认为你知道风险;)

我可以提出两个解决方案:

选项1:

您可以将实际指针隐藏在受保护的部分中,并提供访问功能

class Base1 {
    protected:
    void *ptr
    public:
    Base2 *list() {return (Base2*)ptr;}
};

class Derived1 : public Base1 {
    public:
    Derived2 *list() {return (Derived2*)ptr;}
};
基本上,
Base2::list
将被
Derived2::list
隐藏。请注意,您无法使它们虚拟化并从虚拟性中获益。必须在编译时知道返回类型

选项2:

可以使用模板化基类

template <typename T>
class List {
    public:
    T *list
    //implement all functionality which is common, regardless of the type T
};

class Base1 : public List<Base2> {
    //specifics for Base2 type
};

class Derived1 : public List<Derived2> {
    //specifics for Derived2
};
模板
班级名单{
公众:
T*列表
//实现所有通用的功能,而不考虑T类型
};
Base1类:公共列表{
//Base2类型的详细信息
};
类Derived1:公共列表{
//Derived2的详细信息
};

请注意,在此构造中,Base1和Derived1没有直接关系,而是有一个共同的祖先。

我将从Base1中删除Base2的数组,并使用以下列表创建一个新类:

class Base2{
        int a2;
};

class Derived2: public Base2{
        int b2;
};

class Base1{
};

class Base1WithList : public Base1{
        Base2* list;
};

class Derived1: public Base1{
        Derived2* list;
};

我不认为存在任何简单的方法可以解决你的问题

我会采用以下方法之一:

选择1 将Base2*列表(在base1类中)设为私有,将其隐藏,并将其保存为派生类(derived1)继承的列表。当然,在base1类中定义一个getter函数来访问列表

选择2 只需将base1类中的列表类型更改为(指向)Derived2,并依赖于指向派生类的指针与指向其基类的指针的类型兼容这一事实

template <typename T>
class List {
    public:
    T *list
    //implement all functionality which is common, regardless of the type T
};

class Base1 : public List<Base2> {
    //specifics for Base2 type
};

class Derived1 : public List<Derived2> {
    //specifics for Derived2
};
选择3
忘记继承,使用模板。实例化对象时只需指定类型(Base2*或Derived2*),生活将再次变得美好。

您应该使用模板而不是继承,IMO@onof:从这个问题来看,现在开始讨论模板还为时过早。
Derived2
Base2
,但是
Derived2
的数组不是
Base2
的数组,如果
Derived1
尝试使用依赖
Base2*
指针算法的
Base1
方法,您将遇到问题。(顺便说一句,糟糕的名字。)如果这是你想要的方式,并且你有一个Derived1并在上面调用了Base1方法,从Base1的角度来看,即使数组本身只能存储指向Derived2的指针,将从Base2派生的任何内容放入数组也是完全有效的。@Carl:问题是为什么
Derived1
关心它是
list
中的
Derived2*
而不是
Base2*
s?如果正确使用继承,
list
可以是
Base2*
类型,并包含
Derived2*
的实例,并且可以通过调用
Derived2
中定义的虚拟成员函数来访问
Derived2
中需要的任何特殊行为。