如何使用抽象 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)
你们会如何解决这个问题?
来自java to c++,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();
^^^^^
另请注意:
在第二种情况下,无论您new
ed 必须是delete
d,这样程序就不会泄漏内存。或者,我们有 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;
}
我正在将我的 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)
你们会如何解决这个问题?
来自java to c++,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();
^^^^^
另请注意:
在第二种情况下,无论您
new
ed 必须是delete
d,这样程序就不会泄漏内存。或者,我们有 smart memory managementBase
缺少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;
}