デフォルトコンストラクタについて

解決


くろのすけ  2006-11-09 08:08:58  No: 63537  IP: 192.*.*.*

Visual C++ 2005 EEを使っていますが、下記のようなエラーが出てしまいます。
**************************************************************
d:\\initasign.cpp(13) : error C2228: '.Year' の左側はクラス、構造体、共用体でなければなりません
d:\\initasign.cpp(13) : error C2228: '.Month' の左側はクラス、構造体、共用体でなければなりません
d:\\initasign.cpp(13) : error C2228: '.Day' の左側はクラス、構造体、共用体でなければなりません
**************************************************************
A) ソースプログラムが、

#include <iostream>
#include "Date.h"
using namespace std;

int main()
{

  Date x();              // テスト

  cout << "X = "
     << x.Year() << "年" << x.Month() << "月" << x.Day() << "日\n";

  return 0;
}
で、
B)ヘッダ(Date.h)が、

class Date {
  int  year;    // 西暦年
  int  month;    // 月
  int  day;    // 日

public:
  Date();                  // デフォルトコンストラクタ
};

//--- クラスDateのデフォルトコンストラクタ ---//
Date::Date()
{
  year  = 1;
  month = 1;
  day    = 1;
}
です。デフォルトコンストラクタの使い方に誤りがあるでしょうか?
よろしくお願いします。

編集 削除
tetrapod  2006-11-09 08:26:48  No: 63538  IP: 192.*.*.*

> Date x(); // テスト
典型的間違いです。文法解釈上これは x() という関数が有るものとみなされます。
x という Date 型の変数が欲しい場合は Date x; と書きます。
() がない=初期化子指定がないのでデフォルトコンストラクタが起動されます。

編集 削除
くろのすけ  2006-11-09 08:44:05  No: 63539  IP: 192.*.*.*

あいがとうございます!すっきりしました。

編集 削除
tetrapod  2006-11-09 09:39:03  No: 63540  IP: 192.*.*.*

変数宣言で () を誤用すると関数原型宣言になる、は言語規格書にも注釈がある。

Date x(); は extern Date x(); の省略形とみなされ、つまり
引数はない、返却値は Date 型であるような関数 x() の原型宣言
# { } 内部にも原型宣言を書いて良い
だから例のサンプルで x().Year ならコンパイルに通ったはず (リンクエラー)

っていうか本当に x.Year() でコンパイル通った?

Date x; は変数 x の定義であって、その際に行われる初期化は
引数0個を指定して呼べるコンストラクタによる
int x; も同様 (ビルトインな何もしないコンストラクタが呼ばれると解釈)

Date x(1); は変数 x の定義であって、その際に行われる初期化は
引数1つを指定して呼べるコンストラクタによる
int x(1); も同様 (ビルトインな値変換コンストラクタが呼ばれると解釈)

int x(1, 2); に対応するビルトインコンストラクタはないのでエラー
# カンマ演算子の評価結果による int x(2); にならないらしい
# カンマ演算子を評価させたいのなら int x((1, 2));

編集 削除
YuO  2006-11-09 11:46:25  No: 63541  IP: 192.*.*.*

> っていうか本当に x.Year() でコンパイル通った?

Cから始まるエラーコードなので,コンパイルエラーでは?


> int x; も同様 (ビルトインな何もしないコンストラクタが呼ばれると解釈)

int x = int();
だとxは0になるので,このあたりは説明が難しそうですね……。

編集 削除
くろのすけ  2006-11-09 12:38:55  No: 63542  IP: 192.*.*.*

> っていうか本当に x.Year() でコンパイル通った?

> Cから始まるエラーコードなので,コンパイルエラーでは?

上に書いたヘッダですが、メンバ関数のYear()、Month()、Day()を
記していませんでした。(すみません)
下のようにメンバ関数を追記した状態ですと、
コンパイルが通ります。
(クラスの勉強を始めて日が浅いのでエラーコードのことはよく分からないのですが、変数の宣言と引数を与えないコンストラクタを混同しそうで注意しなければならないと感じました。)

class Date {
  int year; // 西暦年
  int month; // 月
  int day; // 日

public:
  Date(); // デフォルトコンストラクタ
  int Year()  { return year; }    // 年を返却
  int Month()     { return month; }    // 月を返却
  int Day()  { return day; }    // 日を返却
};

編集 削除
tetrapod  2006-11-09 18:02:57  No: 63543  IP: 192.*.*.*

YuO さん
> int x = int(); だとxは0になるので
御意。
POD の初期化は説明が難しいっすね。問題がいろいろ分かれてるし。
・POD コンストラクタが何もしないで結果的に不定値になる場合
・POD コンストラクタが default-initialize の結果 0 を生む場合
・コンストラクタによらず静的変数が zero-initialize される場合
既に C を知ってる人には「自動変数を普通に使うと初期化されん」だけで済むけど。

編集 削除