如何使用抽象 class 作为 for each 循环的索引变量的类型?

How to use an abstract class as the type of the index variable of a for each loop?

我正在将我的 Java 程序翻译成 C++。我在尝试以与 Java.

相同的方式使用 polymorphism 时遇到问题

我的代码看起来像这样:


class Base
{
public:
    virtual void print() = 0;
};

class Derived_1 : public Base
{
public:
    void print()
    {
        std::cout << "1" << std::endl;
    }
};

class Derived_2 : public Base
{
public:
    void print()
    {
        std::cout << "2" << std::endl;
    }
};

接下来是我尝试过的主要方法的两个版本,都给我 编译器错误:

1:

int main(int argc, char const *argv[])
{
    std::vector<Base> v;
    
    v.push_back(Derived_1());
    v.push_back(Derived_2());

    for(Base i: v)
    {
        i.print();
    }

    return 0;
}

错误:

object of abstract class type "Base" is not allowed:C/C++(322)
main.cpp(35, 14): function "Base::print" is a pure virtual function

2:

int main(int argc, char const *argv[])
{
    std::vector<Base*> v;
    
    v.push_back(new Derived_1());
    v.push_back(new Derived_2());

    for(Base* i: v)
    {
        i.print();
    }

    return 0;
}

错误:

expression must have class type but it has type "Base *"C/C++(153)

你们会如何解决这个问题?

来自 to ,take-care还有很多;尤其是内存管理!

在您展示的第一个案例中,您正在对对象进行切片。参见 What is object slicing?

为了访问虚函数,您应该使用 std::vector<Base*>(即指向 Base 的指针的向量),或 std::vector<std::unique_ptr<Base>>std::vector<std::shared_ptr<Base>>(即向量指向 Base).

的智能指针

在您显示的第二个代码中,您的 v 是指向 Base 的指针向量,这意味着您需要通过 -> 运算符访问成员。

即您应该按如下方式访问 print()

i->print();
^^^

或者:

(*i).print();
^^^^^

另请注意:

  • 在第二种情况下,无论您newed 必须是deleted,这样程序就不会泄漏内存。或者,我们有 smart memory management

  • Base 缺少 virtual 析构函数,这将导致 未定义的行为 delete对象。您应该为定义的行为添加一个。参见:When to use virtual destructors?

使用 std::unique_ptr,您的代码将如下所示(示例代码):

#include <memory> // std::unique_ptr, std::make_unique

class Base
{
public:
    virtual void print() /* const */ = 0;
    // add a virtual destructor to the Base
    virtual ~Base() = default;
};

class Derived_1 : public Base
{
public:
    void print() override /* const */ {
        std::cout << "1" << std::endl;
    }
};

class Derived_2 : public Base
{
public:
    void print() override /* const */ {
        std::cout << "2" << std::endl;
    }
};

int main()
{
    std::vector<std::unique_ptr<Base>> v;
    v.reserve(2); // for unwanted re-allocations of memory
    v.emplace_back(std::make_unique<Derived_1>());
    v.emplace_back(std::make_unique<Derived_2>());

    for (const auto& i : v) // auto == std::unique_ptr<Base>
    {
        i->print();
    }
    return 0;
}