指向理解代码的基类的指针列表



我正在接受c++考试的培训,我不明白为什么代码只显示基类的打印函数(也是在我调试代码之后(,而从不打印派生类。你能简单地解释一下为什么吗?我是否可以通过编辑几行代码来显示派生类的打印函数。假设程序生成的数字是:1 67 0 69 0 58 78。

class A
{
int a;
public:
A(int x):a(x){}
void print() { cout << "a=" << a << ' '; }
};
class B:public A
{
int b;
public:
B(int x,int y) :A(x),b(y) {}
void print() { A::print(); cout << "b=" << b << ' '; }
};
int main(){
list<A*> lst;
for (int i = 0; i < 3; i++)
if(rand()%2)
lst.push_back(new A(rand() % 100));
else
lst.push_back(new B(rand() % 100,rand()%100));
for (list<A*>::iterator it = lst.begin(); it != lst.end(); it++)
(*it)->print();
}

您需要声明print()虚拟,这样多态性才能工作。

以下是您提出的格式改进示例,

#include <iostream>
#include <list>
class A{
int a;
public:
A(int x):a(x){}
virtual void print() { std::cout << "a=" << a << ' '; }
};
class B:public A{
int b;
public:
B(int x,int y) :A(x),b(y) {}
void print() override { A::print(); std::cout << "b=" << b << ' '; }
};
int main(){
std::list<A*> lst;
for (int i = 0; i < 30; i++) {
if(rand()%2) {
lst.push_back(new A(rand() % 100));
} else {
lst.push_back(new B(rand() % 100,rand()%100));
}
}
for (std::list<A*>::iterator it = lst.begin(); it != lst.end(); it++) {
(*it)->print();
}
}

我增加了打印元素的数量,因为在这些设置中,我没有得到一个b。上面写着:

  • 如果您不想一次又一次地获得相同的数字,则需要使用srand对代码进行种子设定(并且每个程序只需要对其进行一次种子设定(
  • 如果可能,您应该使用上的C++11提供的new random number生成功能
  • override是可选的,但非常令人鼓舞,它清楚地表明该功能是虚拟的并重新实现了
  • 最重要的是,你需要释放用new分配的内存(使用delete(,或者更好的是,使用@TedLingmo answer中的方法(智能指针(

为了利用动态调度,您需要使A::print()成为virtual。您还需要使A的析构函数virtual能够通过基类指针访问delete对象。

由于您目前没有delete任何对象(而是泄漏所有AB(,我建议您使用智能指针std::unique_ptr<A>,它将在std::list销毁时清理。

示例:

#include <iostream>
#include <list>
#include <memory>   // std::unique_ptr
class A {
int a;
public:
A(int x) : a(x) {}
virtual ~A() = default;  // virtual destructor
virtual void print() { std::cout << "a=" << a << ' '; }
};
class B : public A {
int b;
public:
B(int x, int y) : A(x), b(y) {}
void print() override {
A::print();
std::cout << "b=" << b << ' ';
}
};
int main() {
std::list<std::unique_ptr<A>> lst;   // use of smart pointer
for(int i = 0; i < 30; i++) {
if(rand() % 2) {
lst.emplace_back(std::make_unique<A>(rand() % 100));
} else {
lst.emplace_back(std::make_unique<B>(rand() % 100, rand() % 100));
}
}
for(auto it = lst.begin(); it != lst.end(); it++) {
(*it)->print();
}
// Simpler loop: A range-based for loop:
// for(auto& ptr : lst) ptr->print();
}

最新更新