C++类设计 - 轻松初始化/构建对象

Ken*_*son 6 c++ class-design initialization

使用C++我构建了一个具有许多setter函数的Class,以及在运行时可以连续调用的各种函数.所以我最终得到的代码如下:

A* a = new A();
a->setA();
a->setB();
a->setC();
...
a->doA();
a->doB();
Run Code Online (Sandbox Code Playgroud)

不是,这很糟糕,但我不喜欢一遍又一遍地输入"a->".
所以我重写了我的类定义,如下所示:

class A{
public:
    A();
    virtual ~A();

    A* setA();
    A* setB();
    A* setC();
    A* doA();
    A* doB();

    // other functions

private:

    // vars
};
Run Code Online (Sandbox Code Playgroud)

那么我可以像我一样初始化我的课程:( 方法1)

A* a = new A();
a->setA()->setB()->setC();
...
a->doA()->doB();
Run Code Online (Sandbox Code Playgroud)

(我更喜欢它,因为它更容易编写)
为了更精确地实现这一点,你可以看到我在http://ken-soft.com/?p=234上写的SDL Sprite C++ Class

一切似乎都很好.但是,我对这种方法的任何反馈感兴趣.我注意到一个问题.如果我初始化我的班级:( 方法2)

A a = A();
a.setA()->setB()->setC();
...
a.doA()->doB();
Run Code Online (Sandbox Code Playgroud)

然后我有各种内存问题,有时事情不能正常工作(你可以通过改变我在Sprite Demo的main.cpp中初始化所有Sprite对象的方式来看到这一点).
这是正常的吗?或者行为应该是一样的吗?
编辑 setter主要是为了让我的生活更容易初始化.我的主要问题是方法1和方法2对我来说有什么不同?

编辑: 这是一个getter和setter示例:

Sprite* Sprite::setSpeed(int i) {
    speed = i;
    return this;
}

int Sprite::getSpeed() {
    return speed;
}
Run Code Online (Sandbox Code Playgroud)

Col*_*nee 4

与您的问题无关的一条注释,该声明A a = A();可能没有达到您的预期。在 C++ 中,对象不是默认为 null 的引用类型,因此此语句几乎永远不会正确。你可能只想A a;

A a创建 的新实例A,但该= A()部分调用 的A复制构造函数并构造临时默认值A。如果你这样做了,A a;它就会创建一个A使用默认构造函数的新实例。

如果您没有为类显式实现自己的复制构造函数,编译器将为您创建一个。编译器创建的复制构造函数只会复制另一个对象的数据;这意味着如果您有任何指针,它不会复制指向的数据。

因此,本质上,该行正在创建 的一个新实例A,然后A使用默认构造函数构造另一个临时实例,然后将临时实例复制A到 new 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;
Run Code Online (Sandbox Code Playgroud)

输出将类似于:

Allocated int at 0x9FB7128
Deallocated int at 0x9FB7128
a.myData points to 0x9FB7128
Run Code Online (Sandbox Code Playgroud)

正如你所看到的,a.myData指向一个已经被释放的地址。如果您尝试使用它指向的数据,则可能会访问完全无效的数据,甚至是占据内存中位置的其他对象的数据。然后一旦a超出范围,它就会尝试再次删除数据,这会导致更多问题。