用c++初始化对象
Initializing an object in c++
A.hh
#ifndef A_HH
#define A_HH
#include <iostream>
#include <string>
using namespace std;
class A {
private:
int size;
string name;
public:
A();
~A();
int Load(int, string);
int getSize();
string getName();
/* data */
};
#endif
A.cc:
#include "A.hh"
A::A() {
}
int A::Load(int _size, string _name) {
size = _size;
name = _name;
return 0;
}
int A::getSize() {
return size;
}
string A::getName() {
return name;
}
A::~A() {
}
B.hh:
#ifndef B_HH
#define B_HH
#include "A.hh"
#include <string>
class B {
private:
A* objectA;
public:
B();
B(A*);
~B();
A* getA();
/* data */
};
#endif
B.cc:
#include "B.hh"
B::B() {
}
B::B(A* obj) {
objectA = obj;
}
A* B::getA() {
return objectA;
}
B::~B() {
}
C.cc
#include "C.hh"
C::C() {
}
int C::doSomething() {
cout<<"size = "<<getA()->getSize()<<endl;
cout<<"name = "<<getA()->getName()<<endl;
return 0;
}
C::~C(){
}
C.hh
#ifndef C_HH
#define C_HH
#include "B.hh"
class C : public B {
public:
C();
~C();
int doSomething();
/* data */
};
#endif
main.cc
#include "A.hh"
#include "B.hh"
#include "C.hh"
int main() {
A* objA = new A();
objA->Load(1, "Hello Drew Dormann :)");
B* objB = new B(objA);
C* objC = new C();
objC->doSomething();
return 0;
}
为什么我在doSomething()
上得到一个segfault?
我使用B的子对象来处理解析为B的对象。此外,我必须使用B的孩子来处理A,因为这是更大的东西的一部分,这是简化它的唯一方法。
我不明白为什么会发生这种事。
这个问题背后似乎对对象的工作方式和构造方式存在误解。
C* objC = new C();
创建全新的C。C构造函数除了分配存储之外,什么都不做,所以什么都没有初始化。因为C继承自B,所以C的构造函数将调用B
的默认构造函数,CCD_2什么也不做,而是调用其父级A的默认构造函数。A的默认构造函数不会初始化name
和size
,因此它们的值是未定义的。B的默认构造函数不会初始化objectA
,因此它是未定义的,从而导致segfault。
这个C是由new
创建的,它来自一些内存池,通常是堆,当不再需要时,需要用delete
返回到这个池。如果不是,程序将丢失C.使用的内存
可以在没有动态分配的情况下执行相同的采样。
C objC;
创建一个C,但在堆栈上执行。当堆栈在函数或代码块(搜索词:变量范围(的末尾展开时,C将弹出并自动销毁。这通常是更好的操作方式,因为它不需要额外的内存管理。C会照顾到它的自身,可以被认为是"即发即弃">
回到主题。。。
objC->doSomething();
Do something调用从B继承的getA
方法,该方法尽职尽责地返回未初始化的objectA
。则立即使用CCD_ 10以CCD_ 12作为隐藏的CCD_。由于Crom只知道objectA
实际指向的是什么,如果this->size
没有引发崩溃,那将是一个小奇迹。
如果OP期望
A* objA = new A();
objA->Load(1, "Hello Drew Dormann :)");
和
B* objB = new B(objA);
与C的状态有关。OP不正确。CCD_ 16和CCD_。它们是不同的对象,每个对象都有自己的状态。
为了让C用默认构造函数以外的东西初始化B,你需要你的C构造函数看起来更像这样:
C::C(A* obj) : B(obj)
{
}
这将使用B的B(A*);
构造函数将一个指向a的指针传递给C。
C::C(A* obj,
int size,
string name) : B(obj, size, name)
{
}
B::B(A* obj,
int size,
string name) : A(size, name)
{
}
级联完全指定C所需的所有参数,一直到a.
由于B需要初始化objectA
,我建议删除B和C的默认构造函数,以强制初始化为有意义的值。如果B和C需要默认构造函数用于其他目的,例如存储在标准容器中,则getA()
需要智能得多,或者B的默认构造函数必须将objectA
初始化为某个安全值。
这仍然留下了一个大问题,即为什么B包含指向父级的指针。我将把这个交给OP来解决。
当OP在做这件事的时候,我建议你读一读:什么是三条规则?。因为下一个问题可能是"老兄!谁的deleted
我的objectA
"?
此外,报头中的using namespace std
是非常糟糕的。阅读此处:为什么;使用命名空间std";被认为是不好的做法?
您的问题是objC
中的objectA
指向无效内存,因此在doSomething()
中,您试图在无效指针上调用成员访问运算符。你可以更改B的默认构造函数来构造一个对象,并让objectA指向它,一定要释放你的内存!
#include <iostream>
#include <string>
/*#################
// !! class A !! //
#################*/
class A
{
private:
int size = 0;
std::string name;
public:
int Load(int, const std::string&);
int getSize() { return size; }
std::string getName() { return name; }
};
int A::Load(int _size, const std::string &_name)
{
size = _size;
name = _name;
return 0;
}
/*#################
// !! class B !! //
#################*/
class B
{
private:
A* objectA;
public:
B() : objectA(new A()) { }
B(A* obj) : objectA(new A(*obj)) { }
A* getA() { return objectA; }
virtual ~B() { delete objectA; }
};
/*#################
// !! class C !! //
#################*/
class C : public B
{
public:
C() = default;
int doSomething();
};
int C::doSomething()
{
// Problem: objectA points to invalid memory
std::cout << "size = " << getA()->getSize() << std::endl;
std::cout << "name = " << getA()->getName() << std::endl;
return 0;
}
/*#################
// !!! main !!! //
#################*/
int main()
{
A* objA = new A();
objA->Load(1, "Hello Drew Dormann :)");
B* objB = new B(objA);
C* objC = new C();
objC->doSomething();
// free your memory!!!
delete objA;
delete objB;
delete objC;
return 0;
}
- 用C++中的CPerson(类)类型的对象初始化STL矢量
- 对象初始化中是否允许指向此成员的指针?
- 对象初始化后在C++中显示 char 数组时的异常行为
- 为什么两种不同的对象初始化方式给出不同的输出
- (2 问题)"类"类型重新定义(即使 #pragma 一次),以及静态函数内的静态成员对象初始化?
- afxmem.cpp中的对象初始化差异
- 删除通过取消引用新对象初始化的对象
- 如何使用sregex_token_iterator对象初始化向量
- 关于默认构造函数,对象初始化/使用C++ OOP
- C++ 基元类型初始化与对象初始化
- 哪个函数负责C++全局范围内的类对象初始化?
- C++中构造函数的对象初始化出现问题
- 如何修复模板 BST 类的对象初始化
- 无法在 QML/C++ 中使用绑定对象初始化 UI
- 为什么参数可以在对象初始化时通过赋值运算符传递给构造函数?
- 类对象初始化的二维向量
- GCC:当层次结构中存在虚拟继承时,C++11 内联对象初始化(使用 "this")不起作用
- 对象初始化
- 类对象初始化
- 使用从另一个类继承的类的对象初始化成员对象