C++ 在Base*数据结构中格式化和使用派生类的正确方法是什么? 简介

C++ 在Base*数据结构中格式化和使用派生类的正确方法是什么? 简介,c++,inheritance,vector,derived-class,base-class,C++,Inheritance,Vector,Derived Class,Base Class,我对保存多个派生类的数据结构的正确方法有点迷茫。我对C++比较陌生,如果我有愚蠢的错误/误解,那么抱歉。 目前,我使用了一个向量*,这对我来说很有意义。然而,当我尝试使用向量中包含的对象时,我遇到了一些问题 我遇到的问题 我将使用此示例设置来展示我的问题: Base.h class Base { public: Base(); Base(int a, int b); virtual ~Base(); friend std::ostream& operator<

我对保存多个派生类的数据结构的正确方法有点迷茫。我对C++比较陌生,如果我有愚蠢的错误/误解,那么抱歉。 目前,我使用了一个
向量*
,这对我来说很有意义。然而,当我尝试使用向量中包含的对象时,我遇到了一些问题

我遇到的问题 我将使用此示例设置来展示我的问题:

Base.h

class Base {

 public:
  Base();
  Base(int a, int b);
  virtual ~Base();

  friend std::ostream& operator<<(std::ostream& os, Base& base);

  int getA();
  int getB();

 protected:
  int a;
  int b;

};
在本例中,除了“只使用print()方法”之外,我几乎没有找到解决此问题的可靠建议。我知道我可以解决此问题,但我更愿意了解实现某些东西的正确方法,而不仅仅是避免使用它

那么,当从
向量调用时,是否可能以某种方式执行派生类的重载插入运算符?有朋友功能吗?

#3:标识对象是哪个派生类
intmain(){
向量*对象=新向量();
派生的newderived=新派生的(2,3,4);
Derived2 newderived2=新的Derived2(5,6,7,8);
对象。推回(新派生);
对象。推回(newderived2);

如果(/*objects->front()是派生的*/)cout您正在实现一个非抽象基类。在多态性中,尝试查找基类/派生类中是否存在方法被认为是错误的程序实践。请将常用方法声明为虚拟方法。请这样尝试

class Base {

public:
    Base();
    Base(int a, int b);
    virtual ~Base();

    friend std::ostream& operator<<(std::ostream& os, Base& base);

    virtual int getA();
    virtual int getB();
    virtual int getC() { return 0; }

protected:
    int a;
    int b;

};

class Derived : public Base {

public:
    Derived(int a, int b, int c);
    ~Derived();

    friend std::ostream& operator<<(std::ostream& os, Derived& derived);

    virtual int getA();
    virtual int getB();
    virtual int getC();

private:
    int c;

};

int main() {
    vector<Base*> objects;

    Base* newbase = new Base(0, 1);
    Derived newderived =  Derived(2, 3, 4);
    Base* pnewderived = &newderived;
    objects.push_back(newbase);
    objects.push_back(pnewderived);

    cout << objects.front()->getA() << endl; 
    cout << objects.back()->getA() << endl; 

    cout << objects.back()->getC() << endl; 
}
类基{
公众:
Base();
基础(内部a、内部b);
虚拟~Base();

friend std::ostream&operator您正在实现一个非抽象基类。在多态性中,尝试查找基类/派生类中是否存在某个方法被认为是错误的程序实践。将常用方法声明为虚拟方法。请这样尝试

class Base {

public:
    Base();
    Base(int a, int b);
    virtual ~Base();

    friend std::ostream& operator<<(std::ostream& os, Base& base);

    virtual int getA();
    virtual int getB();
    virtual int getC() { return 0; }

protected:
    int a;
    int b;

};

class Derived : public Base {

public:
    Derived(int a, int b, int c);
    ~Derived();

    friend std::ostream& operator<<(std::ostream& os, Derived& derived);

    virtual int getA();
    virtual int getB();
    virtual int getC();

private:
    int c;

};

int main() {
    vector<Base*> objects;

    Base* newbase = new Base(0, 1);
    Derived newderived =  Derived(2, 3, 4);
    Base* pnewderived = &newderived;
    objects.push_back(newbase);
    objects.push_back(pnewderived);

    cout << objects.front()->getA() << endl; 
    cout << objects.back()->getA() << endl; 

    cout << objects.back()->getC() << endl; 
}
类基{
公众:
Base();
基础(内部a、内部b);
虚拟~Base();

friend std::ostream&operatorIMO您所有的问题都源于试图对抗您选择的解决方案——动态多态性

当每个派生类型共享一个公共接口时,这种技术最为有效。动态多态性的全部要点是调用代码不需要知道或关心实际类型是什么,它只关心它使用一个特定的接口

在您的示例中:

1)您正在尝试使用两个不同的接口。您的动态 多态性通过
Base
接口起作用,您希望使用
派生的
接口。使用动态多态性选择您的接口。如果您需要了解系统给定部分中的特定类型,那么多态性就不是该代码领域的最佳解决方案

2)正确的方法是添加一个
print()
函数。其思想是每个派生类型都知道如何打印自己,因此调用代码不需要知道或关心如何打印

3)在动态多态性失败的系统部分(您需要知道对象的具体类型),则建议使用
dynamic\u cast来发现类型:

if(auto derived = dynamic_cast<Derived*>(objects->front()))
{
     derived->getC(); // Derived specific calls
}
if(auto-derived=dynamic\u cast(objects->front())
{
派生->getC();//派生的特定调用
}
如果指针类型错误,则返回
nullptr
,并且
If()
失败

我在
C++
中发现,对于很多问题来说,动态多态性并不是最好的解决方案。可能会有一种诱惑,那就是尝试将所有问题都动态多态化,但IMO只适用于给定的面向对象设计问题子集


C++
在静态多态性(使用模板引擎)和过程多态性(函数重载)等其他方面也很出色。这些也很值得探索。

IMO您所有的问题都源于试图对抗您选择的解决方案-动态多态性

当每个派生类型共享一个公共接口时,这种技术最为有效。动态多态性的全部要点是调用代码不需要知道或关心实际类型是什么,它只关心它使用一个特定的接口

在您的示例中:

1)您正在尝试使用两个不同的接口。您的动态 多态性通过
Base
接口起作用,您希望使用
派生的
接口。使用动态多态性选择您的接口。如果您需要了解系统给定部分中的特定类型,那么多态性就不是该代码领域的最佳解决方案

2)正确的方法是添加一个
print()
函数。其思想是每个派生类型都知道如何打印自己,因此调用代码不需要知道或关心如何打印

3)在动态多态性失败的系统部分(您需要知道对象的具体类型),则建议使用
dynamic\u cast来发现类型:

if(auto derived = dynamic_cast<Derived*>(objects->front()))
{
     derived->getC(); // Derived specific calls
}
if(auto-derived=dynamic\u cast(objects->front())
{
派生->getC();//派生的特定调用
}
如果指针类型错误,则返回
nullptr
,并且
If()
失败

我在
C++
中发现,对于很多问题来说,动态多态性并不是最好的解决方案。可能会有一种诱惑,那就是尝试将所有问题都动态多态化,但IMO只适用于给定的面向对象设计问题子集

C++
在静态多态性(使用模板引擎)和过程多态性等其他领域也表现出色
class Base {

public:
    Base();
    Base(int a, int b);
    virtual ~Base();

    friend std::ostream& operator<<(std::ostream& os, Base& base);

    virtual int getA();
    virtual int getB();
    virtual int getC() { return 0; }

protected:
    int a;
    int b;

};

class Derived : public Base {

public:
    Derived(int a, int b, int c);
    ~Derived();

    friend std::ostream& operator<<(std::ostream& os, Derived& derived);

    virtual int getA();
    virtual int getB();
    virtual int getC();

private:
    int c;

};

int main() {
    vector<Base*> objects;

    Base* newbase = new Base(0, 1);
    Derived newderived =  Derived(2, 3, 4);
    Base* pnewderived = &newderived;
    objects.push_back(newbase);
    objects.push_back(pnewderived);

    cout << objects.front()->getA() << endl; 
    cout << objects.back()->getA() << endl; 

    cout << objects.back()->getC() << endl; 
}
if(auto derived = dynamic_cast<Derived*>(objects->front()))
{
     derived->getC(); // Derived specific calls
}