如何在使用 std::vector<Base*> 存储派生* 时指定

How to specify while using std::vector<Base*> to store Derived*

本文关键字:gt 存储 派生 Base lt vector std      更新时间:2023-10-16
Class Base{
public:
...
    void do_Something_base();
    string identifier();
    virtual void derived1_specific() {};  // nothing relevant to Base
    virtual int derived2_specific(int) {};
};
Class Derived1:public Base {
public:
...
    string identifier();
    void derived1_specific();
};
Class Derived2:public Base {
public:
... 
    string identifier();
    int derived2_specific();
};

int main() {
   vector<Base*> owner;
   /* push back some Derived1* & Derived2* to owner */
   for (int i = 0; i < owner.size(); i++)
       if (owner->identifier() == "d1")
           owner->derived1_specific(int) 
}

我有一个更大的程序,这就是让我感到困惑的机制。我应该为每个派生类编写虚函数吗?但这非常乏味。我需要获取并设置一些特定的成员,在不同的子类中执行一些特定的功能。什么是更聪明的方法或常用方法?谢谢!

我会非常努力地为特定于子类的方法找到一个通用签名,然后在基类中创建一个可以在没有某种 ID 函数的情况下调用的虚函数。

有时这可以通过将子类特定函数所需的一些附加信息传递给派生类的构造函数来实现,然后可以调用通用方法,例如

virtual void doClassSpecificStuff();

使用派生类的成员变量。

如果你确实需要不同的返回类型等,你可能不想从共同的祖先继承,或者不将所有对象存储在同一个容器中。也许组合在你的上下文中比继承更好(某些类具有特定的工作线程对象而不是 is-a)。

编辑:我删除了虚拟解决方案,因为 OP 澄清他需要传递不同的参数。

由于您有办法知道它的实际类型,因此仅强制转换为它,然后将其用作该类型并没有错:

Class Base{
public:
...
    void do_Something_base();
    string identifier();
};
Class Derived1:public Base {
public:
...
    string identifier();
    void TakeTwoInts(int x, int y);
};
Class Derived2:public Base {
public:
... 
    string identifier();
    const char* ReturnAString();    
};

int main() {
   vector<Base*> owner;
   /* push back some Derived1* & Derived2* to owner */
   for (int i = 0; i < owner.size(); i++)
       switch(owner[i]->identifier())
         {
           case "d1": 
            {
              Derived1* d1 = static_cast<Derived1*>(owner[i]);
              d1->TakeTwoInts(1,2);
              break;
             }
            case "d2":
             {
              Derived2* d2 = static_cast<Derived2*>(owner[i]); 
              printf("%s",d2->ReturnAString());
              break;
             }
            ...
        }
    } 
}

如果您不确定转换是否可行,请改用dynamic_cast:如果您要求的演员表是不可能的,它会返回一个干净的nullptr,而不是垃圾。

顺便说一下,请注意,派生类中的identifier()函数永远不会被调用。要么将 id 存储在可从 Base 访问的变量中,然后不需要每个派生类中的函数,要么必须identifier()为虚函数。

没有:

virtual std::string Base::identifier()

在这种情况下,当你有一个 Base* 时,你不能在它上面调用 identifier()