必须使用指向抽象类的指针会导致困难
我的第一个问题...
我想使用一个抽象类 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;
}
My first question here...
I want to use an abstract class A
from which i derive a class B
(and classes B2
, B3
, ...). I understood that in order to handle them uniformly, I have to use pointers to the base class, so here variables of type A*
.
In the example below, I want to fill aa
which is of type vector<A*>
in function f
. Since I can only use references and the variables lose their scope at the end of f
, I cannot access the members of the entries of aa
in main
anymore.
What could be a solution to this problem?
#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;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
它正在推送本地变量的地址。这就是问题的原因,因为局部变量在从函数返回时被销毁,但
aa
仍然包含指向不存在对象的指针。这样的指针称为悬空指针,使用它调用未定义的行为 - 这是 C++ 中最危险、最令人恼火的方面之一。使用
new
:现在它应该可以工作了。
重要:不要忘记将
~A()
设为虚拟:这是必要的,否则您将无法删除派生类型的对象(在明确定义的类型中)方式),使用基本类型的指针。
It is pushing the address of the local variable. That is the cause of the problem, because the local variable gets destroyed on returning from the functon, but
aa
still contains the pointer to the non-existing object. Such a pointer is called dangling pointer using which invokes undefined behavior - which is one of the most dangerous and irritating aspect of C++.Use
new
:Now it should work.
Important : Don't forget to make
~A()
virtual:It is necessary otherwise you wouldn't be able to delete objects of derived type (in a well-defined way), using the pointers of base type.
您观察到的问题是范围问题。
C++ 中有两种不同的分配策略:
{ }
) 内声明的对象,其生命周期以块结束new
分配的对象> (或者new[]
,如果它是一个数组)如果你想创建一个变量并在它自己的作用域之外访问它,那么你需要依赖动态存储。然而,它不是免费的,因为这样你就会面临生命周期管理问题,因为它现在是手动的。
因此,建议使用 RAII 习惯用法,将动态分配对象的生命周期与自动分配对象的生命周期联系起来。在您的情况下,使用智能指针(或容器)。
使用 C++11:
并相应地更新
foo
:The problem you observe is a matter of scope.
There are two different allocation strategies in C++:
{ }
), its lifetime ends with the blocknew
(ornew[]
if it's an array)If you want to create a variable and access it outside of its own scope, then you need to rely on dynamic storage. However, it's not free, because then you expose yourself to lifetime management issues, since it's now manual.
The recommendation is therefore to use the RAII idiom, to tie the lifetime of a dynamically allocated object to that of an automatically allocated one. In your case, using smart pointers (or containers).
Using C++11:
And updating
foo
accordingly:问题出在您的
f()
函数内。您正在创建一个自动分配的对象,一旦退出该函数,该对象就不再存在。您必须使用new
在堆上分配它。当然,当你不再使用它时,你必须自己释放它。
The problem is within your
f()
function. You are creating a automatically allocated object, that ceases to exist, once you exit the function. You have to allocat it on the heap, usingnew
.Of course you have to free it on your own when you do not use it any more.