所以我最终得到的代码如下:
A* a = new A(); a->setA(); a->setB(); a->setC(); ... a->doA(); a->doB();
不是,这很糟糕,但我不喜欢输入“a->”一遍又一遍地.
所以我重写了我的类定义,如下所示:
class A{ public: A(); virtual ~A(); A* setA(); A* setB(); A* setC(); A* doA(); A* doB(); // other functions private: // vars };
那么我可以像我一样初始化我的课程:(方法1)
A* a = new A(); a->setA()->setB()->setC(); ... a->doA()->doB();
(我更喜欢,因为它更容易写)
为了更精确地实现这一点,你可以看到我在http://ken-soft.com/?p=234写的SDL Sprite C Class
一切似乎都很好.但是,我对这种方法的任何反馈感兴趣.
我注意到一个问题.如果我初始化我的班级:(方法2)
A a = A(); a.setA()->setB()->setC(); ... a.doA()->doB();
然后我有各种内存问题,有时事情不能正常工作(你可以通过改变我在Sprite Demo的main.cpp中初始化所有Sprite对象的方式来看到这一点).
这是正常的吗?或者行为应该是一样的吗?
编辑setter主要是为了让我的生活更容易初始化.我的主要问题是方法1和方法2对我来说有什么不同?
编辑:这是一个getter和setter示例:
Sprite* Sprite::setSpeed(int i) { speed = i; return this; } int Sprite::getSpeed() { return speed; }
解决方法
A创建A的新实例,但是= A()部分调用A的复制构造函数,并使用临时默认构造A.如果你只做了A a;它会使用默认构造函数创建一个新的A实例.
如果没有为类显式实现自己的复制构造函数,编译器将为您创建一个.编译器创建的复制构造函数只会制作另一个对象数据的副本;这意味着如果你有任何指针,它将不会复制指向的数据.
所以,基本上,该行正在创建A的新实例,然后使用默认构造函数构造另一个临时A实例,然后将临时A复制到新A,然后破坏临时A.如果临时A正在获取资源它是构造函数并在它的析构函数中取消分配它们,您可能遇到问题,您的对象试图使用已经解除分配的数据,这是未定义的行为.
以此代码为例:
struct A { A() { myData = new int; std::cout << "Allocated int at " << myData << std::endl; } ~A() { delete myData; std::cout << "Deallocated int at " << myData << std::endl; } int* myData; }; A a = A(); cout << "a.myData points to " << a.myData << std::endl;
输出看起来像:
Allocated int at 0x9FB7128 Deallocated int at 0x9FB7128 a.myData points to 0x9FB7128
如您所见,a.myData指向已解除分配的地址.如果您尝试使用它指向的数据,您可能正在访问完全无效的数据,甚至是访问它的其他对象的数据.然后,一旦你的范围超出范围,它将尝试再次删除数据,这将导致更多问题.