2015-02-10 64 views
1

我正在通過C++的介紹工作,我有一個涉及使用複製構造函數的問題。 練習的想法是構建一個電話對象,它本身構成一個房屋,一根電纜,一個撥號器和一個耳機。這一切都非常有效,並且具有啓發性,因爲每個類在被調用時都會給出一個cout,但是當我嘗試以下操作時會出現問題。問題複製構造一個動態分配的對象

該撥號器構造了12個按鈕的數組。按鈕級看起來如下:

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: 

} ; 

我在撥號程序類的第一槍使用靜態分配的按鈕,並且效果很好。代碼:

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

回答

1

下面的代碼片段調用拷貝構造函數:

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

或者您的數組:

編輯改變通過價值傳遞。

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類中定義的。

編輯:依賴注入樣品添加

我不RLY認爲你需要在你的撥號+按鍵的關係,更像是你的撥號器+手機使用相關的拷貝構造函數。

在這裏你使用拷貝構造函數的樣本(但需要修改的構造以及):

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

段:

{ 
     Button b1; 
     Dialer d(b1); 
    } 

對於你最終將使用12個參數的12個按鈕初始化。也許你應該堅持動態分配,而不是傳遞數組的值,並使用其他類的複製構造函數?

+0

感謝您的快速回答。如果我實現您的提案,它仍然調用Button構造函數,而不是Button複製構造函數。我認爲其中哪一個被調用沒有太大區別,但是練習狀態Dialer應該調用複製構造函數。任何想法如何實現這一目標? – GeneralDuke 2015-02-10 09:08:52

+0

編輯爲使用按價值傳遞。在通過值返回或傳遞一些對象時,通常會使用複製構造函數。 – MichaelCMS 2015-02-10 09:41:03

+0

首先,構造函數12次調用12次(因爲buttons = new Button [12];)。接下來,確實複製構造函數被調用,但之後立即被破壞。我不認爲這也是解決方案... 此外,練習並沒有提到我應該引入一些新的功能。它只是聲明「修改構造函數,析構函數和複製構造函數以實現此更改」 – GeneralDuke 2015-02-10 09:48:27

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]; 
} 
+0

buttons = new Button [12]; 這不會調用複製構造函數嗎?寫作 buttons = dialer.buttons; 不做這項工作。沒有第二組按鈕被構建,運行後我得到「雙免費或腐敗(fasttop)」錯誤。 – GeneralDuke 2015-02-10 09:12:13

+1

@GeneralDuke在這篇文章中的第二個代碼塊是他說你應該放在撥號器 – 2015-02-10 21:52:51

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通常用於執行nting通用容器和類似的,我只是在你的約束內顯示一個解決方案):

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; 
} ; 
+0

的複製構造函數非常感謝這個詳細的解釋。矢量類(它是一個類?)還沒有出現,所以我認爲我不應該使用它。對於賦值運算符也是如此,對於C++ 11來說:對於之前的所有練習,我都使用了舊版本的C++,我認爲這是必需的(儘管它沒有明確說明)。 但是底線:沒有運算符賦值,向量和C++ 11會解決這個問題嗎? – GeneralDuke 2015-02-10 10:09:01

+1

不是,你想要做的是'std :: vector'解決的問題之一。你是通過一本書還是爲了一堂課?如果是一本書,我只需要使用'std :: vector'並完成它,如果它是一個類,我會要求澄清一下賦值運算符。 – TartanLlama 2015-02-10 10:13:01