C++ 同一类函数的多个定义取决于同一继承类的多个类型?

C++ 同一类函数的多个定义取决于同一继承类的多个类型?,c++,inheritance,polymorphism,C++,Inheritance,Polymorphism,是否可以根据继承类的多种类型对同一类函数(多态性)进行多种定义: #include <iostream> #include <vector> #include <string.h> //All base A class class A{ public: int e = 0; virtual int GetE() = 0; //to make A virtual }; class A_A : public A{ p

是否可以根据继承类的多种类型对同一类函数(多态性)进行多种定义:

#include <iostream>
#include <vector>
#include <string.h>
//All base A class
class A{
    public:
        int e = 0;
        virtual int GetE() = 0; //to make A virtual
};
class A_A : public A{
    public:
        A_A(){e=1;}
        virtual int GetE(){return e;}
};
class A_B : public A{
    public:
        A_B(){e=2;}
        virtual int GetE(){return e;}
};
//All base B Class
class B{
    public:
        virtual void ActionOnA(A_A& a){a.e = 100;}
        virtual void ActionOnA(A_B& a){a.e = 200;}
        virtual void ActionOnA(A& a){}
};
class B_A : public B{
    public:
        /*
            B_A as the same behavior of B class but B is virtual
        */
};
class B_B : public B{
    public:
        /*
            B_B do different things on A depending on which A object is passed
        */
        virtual void ActionOnA(A_A& a){a.e += -100;}
        virtual void ActionOnA(A_B& a){a.e += -200;}
        virtual void ActionOnA(A& a){}
};
//now I create a custom A_* class
class A_C : public A{
    public:
        A_C(){e=90;}
        virtual int GetE(){return e;}
};
//Since A_C is never handled anywhere, I must create a new B_* to handle it
//I want it have the behavior of B_A in every A class except for A_C
class B_C : public B_A{
    public:
        virtual void ActionOnA(A_C& a){a.e = 0;}
};

int main(int argc, const char *argv[])
{
    std::vector<A*> AllMyA;
    A_A Object1;
    A_B Object2;
    A_C Object3;
    
    AllMyA.push_back(&Object1);
    AllMyA.push_back(&Object2);
    AllMyA.push_back(&Object3);
    
    B_A test;
    for(A* a : AllMyA){
        test.ActionOnA(*a);
        std::cout << a->GetE() << '\n';
    }
    /*
        Result should be :
            100
            200
            90
        Result is :
            1
            2
            90
    */
    
    AllMyA.clear();
    
    A_A Object4;
    A_B Object5;
    A_C Object6;
    
    AllMyA.push_back(&Object4);
    AllMyA.push_back(&Object5);
    AllMyA.push_back(&Object6);
    
    B_B test2;
    for(A* a : AllMyA){
        test2.ActionOnA(*a);
        std::cout << a->GetE() << '\n';
    }
    /*
        Result should be :
            100
            200
            0
        Result is :
            1
            2
            90
    */
}
#包括
#包括
#包括
//都是基类
甲级{
公众:
int e=0;
virtual int GetE()=0;//创建虚拟
};
A类:公共A{
公众:
A_A(){e=1;}
虚拟int GetE(){return e;}
};
甲乙级:公共甲级{
公众:
A_B(){e=2;}
虚拟int GetE(){return e;}
};
//所有基B类
B类{
公众:
虚空动作A(A_A&A){A.e=100;}
虚空动作A(A_B&A){A.e=200;}
虚拟空操作A(A&A){}
};
B类A:公共B类{
公众:
/*
B_A与B类的行为相同,但B是虚拟的
*/
};
B类:公共B类{
公众:
/*
B_B根据传递的对象的不同,在A上执行不同的操作
*/
虚空动作A(A_A&A){A.e+=-100;}
虚空动作A(A_B&A){A.e+=-200;}
虚拟空操作A(A&A){}
};
//现在我创建了一个自定义的a_*类
A类(丙类)公共A{
公众:
A_C(){e=90;}
虚拟int GetE(){return e;}
};
//由于A_C从未在任何地方处理过,因此我必须创建一个新的B_C*来处理它
//我希望它在每个A类中都有B_A的行为,除了A_C
B_C类:公共B_A{
公众:
虚空动作A(A_C&A){A.e=0;}
};
int main(int argc,const char*argv[]
{
std::载体AllMyA;
A_A Object1;
A_B对象2;
A_C对象3;
AllMyA.push_back(&Object1);
AllMyA.push_back(&Object2);
AllMyA.push_back(&Object3);
B_A测试;
对于(A*A:AllMyA){
试验。行动a(*a);

std::cout GetE()函数
actionA
GetE
之间有很大的区别;
GetE
是一个虚拟函数,因此,编译器在对象的虚拟函数表中写下一个跳转到对应的函数,这是在运行时确定的

然而,当我们看ActionOnA时,编译器需要“知道”在编译时写什么函数(它不是虚拟的!),因此,它会放置最合适的函数重载,即
ActionOnA(A*)
。编译时确定的模板也会出现同样的问题,因此,它不会根据运行时类型选择重载

如前所述,您可以尝试进行可能失败的
动态\u cast
。但在我看来,问题有点不同:

您希望在中有一个动态函数,用于在运行时执行有效操作:

virtual void updateE(bool shouldResetE);
在A_A中:

void updateE(bool shouldResetE) final
{
    this->E = shouldResetE ? 100 : this->E - 100;
}

另外,强烈建议同时使用
override
final
说明符,因为这有助于在编译时捕获错误(
override
在未正确重写函数时发出警告,
final
在继承类时尝试重写此函数时发出警告)。如果A_*不打算从中继承,请使用
final

指定它。您可以使用
dynamic\u cast
@ChrisMM不,它不起作用,因为我不知道A的继承类型(可能稍后,此代码将位于库中,用户将能够重新定义自己的A和B类)。我认为您并不真正理解运行时类型和编译类型之间的区别。正如Karek所提到的,在
actionA
的情况下,它基于静态(编译时)类型,而不是运行时类型。因此您需要
动态\u cast
来调用适当的函数。