キャストとコンストラクタの違い? – プログラミング – Home

キャストとコンストラクタの違い?
 
通知
すべてクリア

[解決済] キャストとコンストラクタの違い?

固定ページ 1 / 2

bun
 bun
(@bun)
ゲスト
結合: 24年前
投稿: 761
Topic starter  

今さらのようにふと疑問に思ったのですが、キャストとコンストラクタによる
初期化って違いはあるんでしょうか?

(例)
以下のようなenumがあるとき、
enum EColor
{
Red = 1,
Blue = 2,
Yellow = 3,
};

EColor eClr = (EColor)2;
で初期化することと
EColor eClr = EColor(2);
で初期化することの違いです。

クラスのときは、コンストラクタかコピーコンストラクタの違い?
だとして、どっちを選んでも差はない?

まぁ、「どっちでもいいやろ」と言われてしまえば、それまでの話なのですが
蛇足ですいません(;^_^A;


引用未解決
トピックタグ
仲澤@失業者
(@uncle_kei)
Prominent Member
結合: 5年前
投稿: 828
 

回答ではありません。あしからず(^^;)。

質問の内容においては、enumは適当な例とはいえません。
なぜなら、enumやunionを継承したクラスは作れないので、
比較が容易にできませんよねぇ。
実際に疑問に思ったときのコードを上げてみてはどうでしょう。


返信引用
bun
 bun
(@bun)
ゲスト
結合: 24年前
投稿: 761
Topic starter  

実際に疑問に思ったのは、上記のenumの例になります。
クラスの話は疑問を抱いてから、自分で考えを広めたものです。

また、そもそも、この話の前提として、
組込型(int, enum, float, ...)とクラス型(class, struct, ...)を分けるべき
かどうかというところも疑問のうちではあります。

私としては組込型とクラス型を分けて考える必要はないのかな?
と思って、上記の質問となります。


返信引用
maru
 maru
(@maru)
ゲスト
結合: 17年前
投稿: 358
 

キャストは明示的変換演算子なので
class_A a;
class_B b = (class_B)a;
の時、class_Aにclass_Bへの明示的変換:
class_A::operator class_B() const;
が必要ですよね。この関数の内部でclass_Bのコンストラクタが使用されるでしょうね。
で、この変換関数が存在しなけば、コンパイルエラーになる。
ただし、class_Bにclass_Aを受け入れるコンストラクタ:
class_B(const class_A& a);
が有れば、そちらが使用される。

ということではないですか?


返信引用
bun
 bun
(@bun)
ゲスト
結合: 24年前
投稿: 761
Topic starter  

ちょっと、質問内容が漠然としすぎていた気がします。
失礼しました。

要は、
1) EColor eClr = (EColor)2;
2) EColor eClr = EColor(2);
どっちの書き方が、より好ましいか?
を迷ったということです。

どっちでもいいような気がするけど、
もしかしたら新発見があるかもと思って質問させていただきました。

「どっちでもいいやろ」
が結論であればクローズとしたいと思いますm(__)m


返信引用
subaru
 subaru
(@subaru)
ゲスト
結合: 19年前
投稿: 381
 

>要は、
> 1) EColor eClr = (EColor)2;
> 2) EColor eClr = EColor(2);
>どっちの書き方が、より好ましいか?
>を迷ったということです。

言語仕様とかは自信が無いですが、
http://msdn.microsoft.com/ja-jp/library/cc440191(VS.71).aspx
の「暗黙のキャスト」の部分を読むとやはり結果的には全く同じようです。
ここの説明では、static_cast の方が危険な操作をしている部分を
後から識別しやすいですよという意味・・・なのかなあ(?)


返信引用
仲澤@失業者
(@uncle_kei)
Prominent Member
結合: 5年前
投稿: 828
 

(あ) EColor eClr = (EColor)2;
(い) EColor eClr = EColor(2);

EColorがenumなので、上記はどちらも「キャスト」です。
下は最近可能になった書き方ですね。
いつから可能になったのかは忘れちゃいました( =>>誰か)。

さて、やってみればすぐわかりますが、EColorがクラスの場合。(あ)も(い)も

 「コンストラクタ EColor( int)「等」があればそれが実行されるが、
   なければコンパイルエラーになる」

だけです。こちらは両方ともコンストラクタ EColor( int)「等」と
解釈されました(VS2008)。

自分としては、クラスの場合は(あ)も(い)もわかりづらいので使いません。

EColor eClr(2); // クラスの場合

と書きますね。これならEColorがenumの場合、コンストラクタがないので、
コンパイルエラーになってくれます。当該のコンストラクタがない場合の
クラスも同様です。逆にenumの場合には、極力キャストしないようにしてます。
せっかく書いた定義なので(vv;)。
で、あえて使うとしたら(あ)ですかねぇ。

蛇足ですが、
classに対してのキャストは、現在では
(1)型B b = static_cast< 型B>( 型Aのインスタンス); // 従来のcast
(2)型B b = dynamic_cast< 型B>( 型Aのインスタンス);  // 主にDown Cast用
(3)型A a = const_cast< 型A>( constな型Aのインスタンス); // const外し用
(4)型B* b = reinterpret_cast< 型B*>( 型Aのインスタンス); // 使うな(らしい)
の4つを使うように推奨されてるそうですが、VCの場合RTTIをOnにしないと
使えなかったりするので、あまり使ってませんね(vv;)。


返信引用
bun
 bun
(@bun)
ゲスト
結合: 24年前
投稿: 761
Topic starter  

>の「暗黙のキャスト」の部分を読むとやはり結果的には全く同じようです。
全く同じですか。
であれば、私はずっと上を使ってきたので、今後もそちらで行こうと思います。

> 下は最近可能になった書き方ですね。
そうなんですね。

>クラスも同様です。逆にenumの場合には、極力キャストしないようにしてます。
>せっかく書いた定義なので(vv;)。
まったく、仲澤@失業者さんのおっしゃるとおりだと思います。
下手にINTとかにキャストするとデバッガで[Red]とか表示されなくなって分かり
づらいことこの上ない。

実際のソースコード上でも、バイナリデータとして保存/読み出しの前後だけ、
固定長のDWORD型にキャストしており、その前後のキャストの話になります。

ありがとうございました。


返信引用
Ban
 Ban
(@ban)
Prominent Member
結合: 5年前
投稿: 776
 

# 重箱の隅的な話です。

> EColorがenumなので、上記はどちらも「キャスト」です。

言語仕様(ISO/IEC14882:2003)上の定義で言えば、
「明示的型変換(explicit type conversion)」に以下の3種類があるので、
・関数形式(functional notation)
・キャスト形式(cast notation)
・型変換演算子(type conversion operator)
単にキャストといえば、cast notationの1)だけを指すと解釈するべきかなと思います。

1) (EColor)2; // $5.4 Explicit type conversion (cast notation)
2) EColor(2); // $5.2.3 Explicit type conversion (functional notation)

効果的には5.2.3は5.4の対応するキャストと等価だと規定されていますし、
現実的には全部ひっくるめてキャストと呼ばれることも多いと思いますけれど。

ちなみに、explict type conversionはenumでもclassでも特に区別はなさ気。

> の4つを使うように推奨されてるそうですが、VCの場合RTTIをOnにしないと
動作上RTTIが必要なのはdynamic_castだけですね。
# 私の場合は言語の機能をOFFにするのが気持ち悪くてOffにはしてません>RTTI

で、「classに対して」に限らず、言語設計者は全般的に1でも2でもなく、
演算子(…_cast類)の使用を薦めてますよね。
# 例えば_castで検索できたり、典型的な誤変換がエラーになったりするので、
# 「何でもできてしまう」上に「識別しにくい」castは好ましくないという発想。

関数形式はtemplateだかで型を画一的に取り扱うために導入されたような…(うろ覚え


返信引用
Ban
 Ban
(@ban)
Prominent Member
結合: 5年前
投稿: 776
 

> 2) EColor(2); // $5.2.3 Explicit type conversion (functional notation)

ちなみに、これでもし引数が複数あれば、初期化とみなされます。
Foo foo =Foo(2,2); はFoo foo(2,2);と等価。


返信引用
ロマ
 ロマ
(@ロマ)
ゲスト
結合: 18年前
投稿: 170
 

関数形式は、初版からあります


返信引用
仲澤@失業者
(@uncle_kei)
Prominent Member
結合: 5年前
投稿: 828
 

Banさん詳しい説明ありがとうございます。
># 私の場合は言語の機能をOFFにするのが気持ち悪くてOffにはしてません>RTTI

確かに、VCも2005あたりからデフォルトでONになってますしね(vv;)。

ロマさん
>関数形式は、初版からあります

ですか、どのコンパイラでしょう。
バージョンは忘れましたが、自分が最初に使ったコンパイラ「Lattice C」は
int( a); はおろか return 0;も使えませんでした(笑)。
それを下敷きにしたと思われるMS-Cのv2.xもだめでした。
少し下ってTurbo C v1.5(サザン版・・・だったかな)も
だめだったような気のせいがします。


返信引用
bun
 bun
(@bun)
ゲスト
結合: 24年前
投稿: 761
Topic starter  

>関数形式は、初版からあります

>バージョンは忘れましたが、自分が最初に使ったコンパイラ「Lattice C」は
int( a); はおろか return 0;も使えませんでした(笑)。

何となくですが、ロマさんは C++ の初版と言っていて、
仲澤@失業者さんは C言語の話をしているのかな?


返信引用
ロマ
 ロマ
(@ロマ)
ゲスト
結合: 18年前
投稿: 170
 

規格制定より前の、
「プログラミング言語C++」(トッパン1988)(原著は1986?)の仕様です
第1版とか1095年版と書いたほうがよいのかな、良くわかりません


返信引用
ロマ
 ロマ
(@ロマ)
ゲスト
結合: 18年前
投稿: 170
 

> 1095年版
1985年版でした


返信引用
固定ページ 1 / 2

返信する

投稿者名

投稿者メールアドレス

タイトル *

プレビュー 0リビジョン 保存しました
共有:
タイトルとURLをコピーしました