C++ 从派生类c+中获取变量+;

C++ 从派生类c+中获取变量+;,c++,class,oop,derived,C++,Class,Oop,Derived,我希望仅当类是特定的派生类时才执行某些操作。就是我有: class X{ int id; } class A: public X{ void run(); } class B: public X{ int lala; } 我想做一些事情,大致如下: main(){ vector<X *> types; types.push_back(new A); types.push_back(new B); int var = 0;

我希望仅当类是特定的派生类时才执行某些操作。就是我有:

class X{
    int id;
}

class A: public X{
    void run();
}

class B: public X{
    int lala;
}
我想做一些事情,大致如下:

main(){
    vector<X *> types;
    types.push_back(new A);
    types.push_back(new B);
    int var = 0;
    for(int i = 0; i<types.size(); i++){
        if(types[i].isType(A)) {types[i].run();} 
    }
    for(int i = 0; i<types.size(); i++){
        if(types[i].isType(B)) {var = lala;} 
    }
}
<>但我不确定C++中我的选择是什么。


谢谢

您可以使用
dynamic\u cast
检查基类指针是否可转换为派生实例

另一种选择是使用一个虚拟函数返回类的
typeinfo
,从而使用该信息将指针强制转换为可转换类型。这可能会更有效,具体取决于
dynamic\u cast
的实现方式。因此,如果您想尝试看看这种方法在您的平台上是否更快,您可以使用它

正如@Jarod42所指出的,您需要一个虚拟函数,在本例中是析构函数,以便
dynamic\u cast
工作。此外,您只需要一个虚拟析构函数,以避免删除实例时出现未定义的行为

范例

#include <iostream>
#include <string>
#include <vector>
#include <typeinfo>

struct A {
    virtual ~A() {

    }

    virtual const std::type_info& getTypeInfo() const {
        return typeid(A);
    }
};

struct B : public A {
    virtual const std::type_info& getTypeInfo() const override {
        return typeid(B);
    }
};

struct C : public A {
    virtual const std::type_info& getTypeInfo() const override {
        return typeid(C);
    }
};



int main()
{
    std::vector<A*> data;
    data.push_back(new A);
    data.push_back(new B);
    data.push_back(new C);

    for (auto& val : data) {
        if (val->getTypeInfo() == typeid(A)) {
            std::cout << "A";
        }
        else if (val->getTypeInfo() == typeid(B)) {
            std::cout << "B";
        }
        else if (val->getTypeInfo() == typeid(C)) {
            std::cout << "C";
        }
        std::cout << std::endl;
    }

    for (auto& val : data) {
        delete val;
    }
}
#包括
#包括
#包括
#包括
结构A{
虚拟~A(){
}
虚拟常量std::type_info&getTypeInfo()常量{
返回类型ID(A);
}
};
结构B:公共A{
虚拟常量std::type_info&getTypeInfo()常量重写{
返回类型ID(B);
}
};
结构C:公共A{
虚拟常量std::type_info&getTypeInfo()常量重写{
返回类型ID(C);
}
};
int main()
{
std::矢量数据;
数据。推回(新A);
数据。推回(新B);
数据。推回(新C);
用于(自动和val:数据){
如果(val->getTypeInfo()==typeid(A)){
std::cout getTypeInfo()==typeid(B)){
std::cout getTypeInfo()==typeid(C)){
std::cout您正在寻找的

#包括
使用名称空间std;
X类{
公众:
int-id;
virtual~X()=默认值;
};
A类:公共X{
公众:
无效运行(){}
};
B类:公共X{
公众:
内特拉;
};
main(){
媒介类型;
类型。推回(新A);
类型。推回(新B);
int-var=0;

对于(inti=0;i这个问题的现代C++17解决方案是使用变量向量,即
std::vector我有两个想法

为什么不使用一个共享方法来返回一个值,该值给出了它是a还是B的上下文?例如,如果lala只返回0或更大的值,那么可以使用void run()代替int run()并始终返回-1

class X {
   int id;
   virtual int run() = 0; //Assuming X isn't meant to be instantiated
}

class A: public X {
   // Return -1 to differentiate between As and Bs
   int run() { return -1; }
}

class B: public X {
   int lala;
   int run() { return lala;}
}
那么你有

main(){
vector<X *> types;
types.push_back(new A);
types.push_back(new B);
int var = 0, temp = 0;

for( int i = 0; i<types.size(); i++ ) {
    if( (temp = types[i].run()) != -1 )
        var = temp;
        ....
    }
}
main(){
vector<X *> types;
types.push_back(new A);
types.push_back(new B);
int var = 0;

for( int i = 0; i<types.size(); i++ ) {
    if( types[i].isA == true ) {
        types[i].run();
    }
    else {
        var = types[i].lala;
    }
}
那么你有

main(){
vector<X *> types;
types.push_back(new A);
types.push_back(new B);
int var = 0, temp = 0;

for( int i = 0; i<types.size(); i++ ) {
    if( (temp = types[i].run()) != -1 )
        var = temp;
        ....
    }
}
main(){
vector<X *> types;
types.push_back(new A);
types.push_back(new B);
int var = 0;

for( int i = 0; i<types.size(); i++ ) {
    if( types[i].isA == true ) {
        types[i].run();
    }
    else {
        var = types[i].lala;
    }
}
main(){
媒介类型;
类型。推回(新A);
类型。推回(新B);
int-var=0;

对于(int i=0;i
dynamic\u cast
需要至少一个虚拟方法(作为析构函数)。“这通常比
dynamic\u cast
性能更好。”-为什么编译器要实现一些功能完全相同但速度较慢的东西?请引用一个源代码。
getTypeInfo
的定义可能会被复制粘贴到所有地方。在这里必须非常小心。您仍然必须以某种方式强制转换它以访问其成员。您可以使用
static\u cast
这不会带来任何开销,除非您由于多重继承而需要横向转换。那么您无论如何都必须使用
dynamic\u cast
。这也回答了@ChristianHackl的问题-编译器必须为
dynamic\u cast
做一些更聪明的事情来支持横向转换。我可能应该尽量避免这样做泛化:PSo
X
只是为了让它们保持在同一个向量中?修复漏洞不会有什么坏处。谢谢Goran。我想还有一个小问题是,如果a和B都有派生类,那么相同的if语句会对派生类起作用吗。也就是说,如果C是从a派生的,我们用“if(auto ta=dynamic_cast(types[i])”会返回真值吗?@ChristianHackl我知道,我想更改最小的codo量以使其可编译-问题不是泄漏:)但是我会添加带有固定漏洞的代码以供参考。@Davelas是的,如果
C
是从
A
派生的,它也会起作用,并且它将通过
A
的路径。请注意,@Rabster的解决方案并非如此。我还想指出,过度使用
dynamic\u cast
通常是糟糕的代码设计的标志。我不知道这是一个精确的应用程序,但是如果您试图对一组对象执行操作,这取决于对象的运行时类型,那么您可能正在寻找访问者设计模式:这是解决此问题的一个很好的解决方案(并且比
dynamic\u cast
变体的性能更好),但我只想指出,如果我们向层次结构中添加新类,并且希望在
类型中也添加它们,那么它将不再有效,除非我们更改向量的签名。
main(){
vector<X *> types;
types.push_back(new A);
types.push_back(new B);
int var = 0, temp = 0;

for( int i = 0; i<types.size(); i++ ) {
    if( (temp = types[i].run()) != -1 )
        var = temp;
        ....
    }
}
class X {
    int id;
    bool isA;
}

class A: public X {
    A() : isA(true) { };
    void run();
}

class B: public X {
    B() : isA(false) { } ;
    int lala;
}
main(){
vector<X *> types;
types.push_back(new A);
types.push_back(new B);
int var = 0;

for( int i = 0; i<types.size(); i++ ) {
    if( types[i].isA == true ) {
        types[i].run();
    }
    else {
        var = types[i].lala;
    }
}