C言語関係掲示板

過去ログ

No.367.C++のコンストラクタについて

[戻る] [ホームページ]
No.2433

C++のコンストラクタについて
投稿者---しょうじ(2002/08/20 17:01:00)


C++にはコンストラクタ(クラスオブジェクトの初期化)というものがありますが、
実際どのように宣言し、どう使用するかがわかりません。
ここのHPのリンク先も拝見させていただきましたが、いまいち理解できませんでした。
どなたか簡単な解説をお願いいたします。

No.2436

Re:C++のコンストラクタについて
投稿者---TDa(2002/08/20 21:17:24)


>どなたか簡単な解説をお願いいたします。

ここってC++の質問はOKなんでしょうか。
コンストラクタを簡単に解説なんてとても無理なんだけど。
本当に簡単にいうと
「インスタンスを生成し初期値を与える」
という感じでしょうか。

No.2472

Re:C++のコンストラクタについて
投稿者---たか(2002/08/22 20:38:08)


コンストラクタにはクラス名と同名を与えます。戻り値はありません。

class CLASS {
  int i;
public:
  CLASS(int j = 0) : i(j) {}
};

同様にデストラクタにはクラス名と同名で、"~"(チルダ)をつけます。
  ~CLASS() {}

というように。

No.2478

Re:C++のコンストラクタについて
投稿者---たか(2002/08/23 14:17:19)


簡単なコンストラクタとデストラクタの例をあげます。
main関数にreturn文がないのは、忘れたのではありません。C++では
returnがないと、暗黙のうちに0を返します。

#include <iostream>
#include <string>

class Class {
  char *buf;
public:
  Class(char *str) {
    buf = new char[strlen(str) + 1];
    strcpy(buf, str);
  }
  ~Class() { delete[] buf; }
  friend std::ostream &operator<<(std::ostream &os, Class &cl) {
    os << cl.buf;
    return os;
  }
};

int main()
{
  Class cl("test");
  
  std::cout << cl << std::endl;
}


No.2481

Re:C++のコンストラクタについて
投稿者---かずま(2002/08/23 18:26:12)


> 簡単なコンストラクタとデストラクタの例をあげます。

コンストラクタで new して、デストラクタで delete するクラスは、
コピーコンストラクタや代入演算子をきちんと定義するか、あるいは
それらを private にして使えなくするようにしないと、問題になる
ことがありますよ。

だから、この例は、コンストラクタとデストラクタの説明としては、
あまり適切なものとは言えないような気がしますが、どうでしょう。

たとえば、次のコードを実行するとどうなるか考えてみてください。
int main()
{
    Class c1("test1");
    Class c2("test2");
    c1 = c2;
}


No.2482

Re:C++のコンストラクタについて
投稿者---たか(2002/08/23 20:27:28)


かずまさんすみません。

では、何か適当な例を見せてください。

No.2483

Re:C++のコンストラクタについて
投稿者---TDa(2002/08/23 22:21:29)


>かずまさんすみません。
>では、何か適当な例を見せてください。

かずまさんご指名に横から失礼します。
かずまさんご指摘のようにコンストラクタ、デストラクタといってもまともに動
かそうとするといろんなところに手を入れなきゃならないのがC++の難しいところ
ですよね。

ちなみに
「メモリを動的に割り当てるクラスではコピーコンストラクタと代入演算子を宣言しよう」
というのはEffectiveC++の11項です。

こんなコードを書いてみました。

#include <iostream>

//クラスFoo何もしないクラス。
class Foo {
    //メンバ無し
public:
    //デフォルトコンストラクタ
    Foo()   { std::cout << "コンストラクタが呼ばれました。" << std::endl; }
    //コピーコンストラクタ
    Foo(Foo& x) { std::cout << "コピーコンストラクタが呼ばれました。" << std::endl; }
    //デストラクタ。
    ~Foo()  { std::cout << "デストラクタが呼ばれました。"   << std::endl; }
};

int main()
{
    Foo foo;
    Foo* pfoo = new Foo;
    Foo bar = foo;
    
    delete pfoo;
    return 0;
}



No.2485

Re:C++のコンストラクタについて
投稿者---たか(2002/08/24 16:01:33)


TDaさんどうもです。

できれば、代入演算子(char *とconst CLASS &を引数に取るもの)も
定義した方がいいようですね。

コピーコンストラクタはあくまでオブジェクト構築時に呼び出される
ものですから。

No.2490

Re:C++のコンストラクタについて
投稿者---TDa(2002/08/25 00:37:24)


こんばんは。たかさんのコードに手を入れてみました。
operator=(const char*)を定義してないですがデフォルトコンストラクタが
変換コンストラクタをかねているので動作には問題ありません。(メッセージでわかる)

もちろんよけいなコンストラクタ、デストラクタの呼び出しをさけるために
operator=(const char*)を多重定義した方がいいとおもいます。

#include <iostream>
#include <cstring>

class Class {
    char* buf;
public:
    //default constructor
    //conversion constructor const char* => Class
    Class(const char* str = NULL) {
        std::cout << "デフォルトコンストラクタが呼ばれました。" << std::endl;
        if (str == NULL) {
            buf = new char[1];
            *buf = '\0';
            return;
        }
        
        buf = new char[std::strlen(str) + 1];
        std::strcpy(buf, str);
    }
    //copy constructor
    Class(const Class& c) {
        std::cout << "コピーコンストラクタが呼ばれました。" << std::endl;
        buf = new char[std::strlen(c.buf) + 1];
        std::strcpy(buf, c.buf);
    }
    //destructor
    ~Class() { 
        std::cout << "デストラクタが呼ばれました。" << std::endl;
        delete[] buf; 
    }
    
    Class& operator=(const Class& x) {
        //自身への代入のチェック
        if (&x == this) 
            return *this;
        
        delete[] buf;
        buf = new char[std::strlen(x.buf) + 1];
        std::strcpy(buf, x.buf);
        
        return *this;
    }
    
    friend std::ostream& operator<<(std::ostream& os, Class& cl) {
        os << cl.buf;
        return os;
    }
};

int main()
{
    Class cl("test");
    Class kurasu(cl);
    Class klass;
    
    kurasu = "hoge";    //変換コンストラクタ
    klass = cl;
  
    std::cout << cl << std::endl;
    std::cout << kurasu << std::endl;
    std::cout << klass << std::endl;
    
    return 0;

}


No.2492

Re:C++のコンストラクタについて
投稿者---たか(2002/08/25 10:43:07)


TDaさん分かりやすいサンプルありがとうございます。

なるほど、変換コンストラクタとして使う事により、右辺の文字列リテラ
ルがクラスに格上げされるんですね。intがdoubleに格上げになるのと
よく似ていますね。