C++ 必须使用指向抽象类的指针会带来困难
我的第一个问题是 我想使用一个抽象类C++ 必须使用指向抽象类的指针会带来困难,c++,pointers,abstract-class,C++,Pointers,Abstract Class,我的第一个问题是 我想使用一个抽象类A,从中派生一个类B(和类B2,B3,…)。我知道为了统一处理它们,我必须使用指向基类的指针,所以这里是A*类型的变量 在下面的示例中,我想在函数f中填充aa类型的vector。由于我只能使用引用,并且变量在f末尾失去作用域,因此我无法再访问main中aa项的成员 这个问题的解决方案是什么 #include <vector> #include <iostream> class A { public: virt
A
,从中派生一个类B
(和类B2
,B3
,…)。我知道为了统一处理它们,我必须使用指向基类的指针,所以这里是A*
类型的变量
在下面的示例中,我想在函数f
中填充aa
类型的vector
。由于我只能使用引用,并且变量在f
末尾失去作用域,因此我无法再访问main
中aa
项的成员
这个问题的解决方案是什么
#include <vector>
#include <iostream>
class A {
public:
virtual int getVar(int, int) = 0;
};
class B : public A {
public:
B(std::vector<std::vector<int> > var) : var_(var) {};
int getVar(int i, int j) { return var_[i][j]; }
private:
std::vector<std::vector<int> > var_;
};
void f(std::vector<A*>& aa) {
std::vector<std::vector<int> > var(1, std::vector<int>(1));
var[0][0] = 42;
B b(var);
aa.push_back(&b);
}
int main() {
std::vector<A*> aa;
f(aa);
std::cout << aa[0]->getVar(0, 0) << std::endl;
return 0;
}
#包括
#包括
甲级{
公众:
虚拟int getVar(int,int)=0;
};
B类:公共A{
公众:
B(std::vectorvar):var_(var){};
intgetvar(inti,intj){returnvar_ui][j];}
私人:
std::向量变量;
};
空f(标准::向量和aa){
std::vector var(1,std::vector(1));
var[0][0]=42;
B(var);
aa.推回(&b);
}
int main(){
std::载体aa;
f(aa);
std::coutgetvar(0,0)
它正在推送局部变量的地址。这是问题的原因,因为从函数返回时局部变量会被破坏,但aa
仍然包含指向不存在对象的指针。这种指针被称为using,它调用未定义的行为,这是最危险的行为之一C++的刺激性方面。
使用新建:
aa.push_back(new B(var));
现在应该可以了
重要提示:别忘了将~A()
虚拟化:
class A {
public:
virtual ~A() {} //MUST DO IT
virtual int getVar(int, int) = 0;
};
这是必需的,否则您将无法使用基类型的指针(以定义良好的方式)删除派生类型的对象。问题出在您的f()中
函数。您正在创建一个自动分配的对象,一旦退出该函数,该对象就不再存在。您必须使用new
在堆上分配它
B* b = new B(var);
aa.push_back(b);
当然,当你不再使用它时,你必须自己释放它
int main() {
...
for (std::vector<A*>::iterator it = aa.begin(); it != aa.end(); ++it)
{
delete *it;
}
return 0;
}
intmain(){
...
for(std::vector::iterator it=aa.begin();it!=aa.end();++it)
{
删除*它;
}
返回0;
}
您观察到的问题是范围问题
C++中有两种不同的分配策略:
- 自动存储:在块(
{}
)中声明的对象,其生命周期以块结束
- 动态存储:分配有
new
(或new[]
的对象(如果是数组)
如果你想创建一个变量并在它自己的作用域之外访问它,那么你需要依赖动态存储。但是,它不是免费的,因为这样你就会暴露出生命周期管理的问题,因为它现在是手动的
因此,建议使用RAII习惯用法,将动态分配对象的生存期与自动分配对象的生存期联系起来
使用C++11:
int main() {
std::vector< std::unique_ptr<A> > aa;
foo(aa);
std::cout << aa.front()->getVar(0,0) << "\n";
}
非常感谢您快速详细的回答!
int main() {
std::vector< std::unique_ptr<A> > aa;
foo(aa);
std::cout << aa.front()->getVar(0,0) << "\n";
}
void foo(std::vector< std::unique_ptr<A> >& aa) {
std::vector<std::vector<int> > var(1, std::vector<int>(1));
var[0][0] = 42;
aa.push_back(new B(var));
}