复制构造动态分配对象的问题

时间:2015-02-10 08:54:28

标签: c++ copy-constructor dynamic-allocation

我正在使用C ++简介,我遇到了涉及使用复制构造函数的问题。 练习的想法是构建一个Telephone对象,它本身构建一个Housing,Cable,Dialer和Headset。这一切都很有效,也很有启发性,因为每个类在调用时会给出一个cout,但是当我尝试以下内容时会出现问题。

Dialer构造了一个包含12个按钮的数组。 Buttons类看起来如下:

class Button {
public:

  Button() { std::cout << "Button Constructor " << this << std::endl ; }
  Button(const Button&) { std::cout << "Button Copy Constructor " << this << std::endl ; }
  ~Button() { std::cout << "Button Destructor " << this << std::endl ; }

private:

} ;

我在Dialer类中的第一个镜头使用按钮的静态分配,这很有效。代码:

class Dialer {
public:

  Dialer() {        std::cout << "Dialer Constructor " << this << std::endl ; }
  Dialer(const Dialer &dialer) : buttons(dialer.buttons) {      std::cout << "Dialer Copy Constructor " << this << std::endl ; }
  ~Dialer() { std::cout << "Dialer Destructor " << this << std::endl ; }

private:

  Button buttons[12] ;

} ;

练习的下一步是动态分配按钮,以及乐趣开始的地方。以下代码可以使用:

class Dialer {
public:

  Dialer() : buttons(new Button[12]) { std::cout << "Dialer Constructor " << this << std::endl ; }

  Dialer(const Dialer &dialer) {
        buttons = new Button[12];
        std::cout << "Dialer Copy Constructor " << this << std::endl ;
    }

  ~Dialer() {
            delete[] buttons;
            std::cout << "Dialer Destructor " << this << std::endl ;
    }

private:

  Button* buttons ;
} ;

但当然这并没有调用Button复制构造函数。我尝试过很多东西:

buttons = new Button(dialer.buttons)[12];
buttons = new Button(dialer.*buttons)[12];
*buttons = dialer.*buttons;

但我无法解决这个问题。所有这些尝试都会给出一个错误,即Button类中没有定义匹配函数。

我将不胜感激任何帮助:)

干杯, GeneralDuke

3 个答案:

答案 0 :(得分:1)

以下代码段调用复制构造函数:

 Button b;
 Button a=b; // copy constructor called

或者您的阵列:

EDIT已更改为按值传递。

void addToArray(Button* arr, Button aButton, int idx)
{
    arr[idx]=aButton;
}

buttons = new Button[12];

for (int i=0;i<12;i++)
{
     addToButtons(buttons,dialer.buttons[i],i);
}

请注意,您在Button类上定义了复制构造函数,而不是在ArrayOfButtons类上定义。

编辑:添加依赖注入样本

我不认为你需要在Dialer + Button关系上使用复制构造函数,更像是Dialer + Phone关系。

以下是使用复制构造函数的示例(但它也需要修改后的构造函数):

    class Dialer
    {
       public:
         ...
         Dialer(Button& but):b(but){};
         ....
       private:
         Button b;
    }

摘录:

    {
         Button b1;
         Dialer d(b1);
    }

对于12个按钮,在初始化时最终会使用12个参数。也许你应该坚持动态分配,而不是传递数组的值,并将复制构造函数用于其他类?

答案 1 :(得分:1)

以下代码格式调用复制构造函数。

Button a;
Button b=a; //calls the copy constructor of Button class
Button c;
c = a; // calls the overload assignment operator, but not the copy constructor.!

在您的情况下,对于实例数组,

buttons = new Button[12];

for (int i=0;i<12;i++)
{
     buttons[i] = dialer.buttons[i];
} 

答案 2 :(得分:1)

使用operator new[]将使用他们的无参数构造函数构造那些Button。使用=进一步分配将调用赋值运算符。

如果您确实需要调用复制构造函数,则有三个选项:

首先,只使用std::vector<Button>代替Button[12]。这将处理您的分配和释放,并具有您想要的复制语义:

class Dialer {
public:

    Dialer() : buttons(12) { std::cout << "Dialer Constructor " << this << std::endl ; }

    Dialer(const Dialer &dialer) : buttons(dialer.buttons) {
        std::cout << "Dialer Copy Constructor " << this << std::endl ;
    }

    ~Dialer() { std::cout << "Dialer Destructor " << this << std::endl ; }

private:

    std::vector<Button> buttons;
} ;

您的第二个选择是根据复制构造函数定义赋值运算符,通常称为复制和交换习语:

Button& operator= (Button other) { /*do swapping*/ }

您的第三个选择是使用std::allocator分配内存并在单独的步骤中构建它,允许您调用复制构造函数来构造对象(注意,在实践中永远不要这样做; std::allocator通常用于实现通用容器等,我只是在你的约束中显示一个解决方案):

class Dialer {
public:

    Dialer() : buttons() {
        std::allocator<Button> b_alloc;
        buttons = b_alloc.allocate(12);
        for (int i=0; i<12; i++)
        {
            b_alloc.construct(buttons+i); //this line requires C++11
        }

        std::cout << "Dialer Constructor " << this << std::endl ; }

    Dialer(const Dialer &dialer) {
        std::allocator<Button> b_alloc;
        buttons = b_alloc.allocate(12);
        for (int i=0; i<12; i++)
        {
            b_alloc.construct(buttons+i, dialer.buttons[i]);
        }
        std::cout << "Dialer Copy Constructor " << this << std::endl ;
    }

    ~Dialer() {
        std::allocator<Button> b_alloc;
        for (int i=0; i<12; i++)
        {
            b_alloc.destroy(buttons+i);
        }
        b_alloc.deallocate(buttons, 12);
        std::cout << "Dialer Destructor " << this << std::endl ;
    }

private:

    Button* buttons;
} ;