携帯を毎朝フル充電しているにも関わらず、会社に着くまでには電池残量不足で電源が切れます。
電車内ではiチャネルでニュース見てるだけなんですけど、数ページ見ただけで残量が減っていき、一瞬で電池残量不足になります。全く使い物になりませぬ!
電池パックを取り出して見るとお餅のように丸くなっています。電池パックのあまりの丸さに、裏の蓋もなかなか閉まらないくらいです。こりゃもう寿命だなー。
この記事にコメントする
目次: C言語とlibc
(説明は後述)
コードとVC++ のプロジェクトファイルを固めたものへのリンク。
C++ の超有名ライブラリboostに、デフォルトのコピー操作をコンパイル時点でエラーにしてくれるboost::noncopyableという便利クラスがあります。
C++ ではコピー操作(コピーコンストラクタやoperator=)が未定義のクラスでコピー操作を行うと、デフォルトのコピーが働きます。しかしポインタをコピーしてしまうなど、デフォルトのコピーでは困るケースがあります。boost::noncopyableを使うと、気づかないうちに意図しないコピーを使っていないかどうかを、コンパイル段階で検出できるのです。便利でしょ。
前置きが長くなりましたが、私もこれはいいなと思って使ってみたのですが、g++ 4.3.2では何も言われないのに、VC++ 2010だとエラーになってしまい困っています。
私の使い方が何か間違っているだけかもしれませんが、同じコードをコンパイルしてもg++ 4.3.2は何も言いません。しかもVC++ 2010の出すエラーメッセージが意味不明すぎてどこをどう直せばいいのかわからんのです…。
コピーOKなクラスAと、コピーNGな(Uncopyable(※1)を継承)クラスBを多重継承した、クラスCを定義(※2)します。このオブジェクトを例外で投げる(main() のthrow C(); の部分)ということがしたいのです。
その際g++ 4.3.2は何も言わないし、できた実行ファイルも正常に動作もしますが、VC++ 2010は「そんなことはできねーよ!」とお怒りになり、コンパイルエラーにされてしまいます。
A <-----------------+-- C
Uncopyable <-- B <--'
しかし、クラスBを取っ払って、下記のように多重継承したクラスDを使うとVC++ も文句を言わなくなります。
A <-----------------+-- D
Uncopyable <--------'
(※)Uncopyableクラスは、boost::noncopyableのコピペにデバッグメッセージを追加しただけのクラスです。
(※2)コピーOKとコピーNGを多重継承するなんて、コピーOKなのかNGなのか矛盾してますよ、テメーの設計はおかしいですよ。という突っ込みはその通りなのですが、今は設計の話ではないので無視して進めてます。
コードは下記の通りです。先頭の #define USE_CLASS_Cを有効にするとパターン1、コメントアウトなどして無効にするとパターン2となります。
#include <iostream>
#include <cstdio>
//#define USE_CLASS_C
class Uncopyable {
protected:
Uncopyable() {
std::cout << "Uncopyable::Uncopyable()" << std::endl;
}
~Uncopyable() throw() {
std::cout << "Uncopyable::~Uncopyable()" << std::endl;
}
private:
Uncopyable(const Uncopyable&);
const Uncopyable& operator=(const Uncopyable&);
};
class A {
public:
A() {
std::cout << "A::A()" << std::endl;
}
virtual ~A() {
std::cout << "A::~A()" << std::endl;
}
virtual const char *func() {
return "A";
}
};
class B : private Uncopyable {
public:
B() {
std::cout << "B::B()" << std::endl;
}
virtual ~B() {
std::cout << "B::~B()" << std::endl;
}
};
#ifdef USE_CLASS_C
class C : public A, public B {
public:
C() : A(), B() {
std::cout << "C::C()" << std::endl;
}
virtual ~C() {
std::cout << "C::~C()" << std::endl;
}
C(const C& c) : A(), B() {
std::cout << "C::C(const C& c)" << std::endl;
}
virtual const char *func() {
std::cout << "C::func()" << std::endl;
return "C";
}
};
#else
class D : public A, private Uncopyable {
public:
D() : A(), Uncopyable() {
std::cout << "D::D()" << std::endl;
}
virtual ~D() {
std::cout << "D::~D()" << std::endl;
}
D(const D& d) : A(), Uncopyable() {
std::cout << "D::D(const D&)" << std::endl;
}
virtual const char *func() {
std::cout << "D::func()" << std::endl;
return "D";
}
};
#endif
int main(int argc, char *argv[])
{
try {
std::cout << "try0" << std::endl;
#ifdef USE_CLASS_C
throw C();
#else
throw D();
#endif
} catch (A& e) {
std::cout << "catch0" << std::endl;
std::cout << "---- " << e.func() << std::endl;
}
getchar();
}
コピペするのすら面倒くさい方のために、
コードとVC++ のプロジェクトファイルを固めたものを置きます。全コードの著作権は放棄しますが、Uncopyableクラスはboostライブラリboost::noncopyableの派生物です。
コンパイルと実行結果は下記の通りです。
パターン1 VC++(エラー)、g++(OK)、パターン2 VC++(OK)、g++(OK)の順に、コンパイル結果と、実行結果を連続して掲載しています。
まずはUncopyableを直接継承していないパターン(パターン1)です。VC++ の結果です。
1>------ ビルド開始: プロジェクト: noncopyable, 構成: Debug Win32 ------ 1> a.cpp 1>y:\projects\c\test\test_noncopyable\a.cpp(55): error C2248: 'Uncopyable::Uncopyable' : privateメンバー (クラス 'Uncopyable' で宣言されている) にアクセスできません。 1> y:projectsctesttest_noncopyablea.cpp(17) : 'Uncopyable::Uncopyable' の宣言を確認してください。 1> y:projectsctesttest_noncopyablea.cpp(7) : 'Uncopyable' の宣言を確認してください。 1> コンパイラでのこの診断により関数 'B::B(const B &)' が生成されました。 ========== ビルド: 0正常終了、1失敗、0更新不要、0スキップ ==========
次にg++ の結果です。
$ g++ -Wall -DUSE_CLASS_C a.c -o c.out $ ./c.out try0 A::A() Uncopyable::Uncopyable() B::B() C::C() catch0 C::func() ---- C C::~C() B::~B() Uncopyable::~Uncopyable() A::~A()
次、クラスBを継承ツリーから省いてUncopyableを直接継承しているパターン(パターン2)です。VC++ の結果です。
try0 A::A() Uncopyable::Uncopyable() D::D() catch0 D::func() ---- D A::a = 0 D::~D() Uncopyable::~Uncopyable() A::~A()
次にg++ の結果です。
$ g++ -Wall a.c -o d.out $ ./d.out try0 A::A() Uncopyable::Uncopyable() D::D() catch0 D::func() ---- D D::~D() Uncopyable::~Uncopyable() A::~A()
な、なぜだ…。一体、何が間違っているというのだ…。
この記事にコメントする
| < | 2010 | > | ||||
| << | < | 06 | > | >> | ||
| 日 | 月 | 火 | 水 | 木 | 金 | 土 |
| - | - | 1 | 2 | 3 | 4 | 5 |
| 6 | 7 | 8 | 9 | 10 | 11 | 12 |
| 13 | 14 | 15 | 16 | 17 | 18 | 19 |
| 20 | 21 | 22 | 23 | 24 | 25 | 26 |
| 27 | 28 | 29 | 30 | - | - | - |
25年10月6日
25年10月6日
25年9月29日
25年9月29日
20年8月24日
20年8月24日
16年2月14日
16年2月14日
25年7月20日
25年7月20日
25年7月20日
25年7月20日
25年7月20日
25年7月20日
20年8月16日
20年8月16日
20年8月16日
20年8月16日
24年6月17日
24年6月17日
wiki
Linux JM
Java API
2002年
2003年
2004年
2005年
2006年
2007年
2008年
2009年
2010年
2011年
2012年
2013年
2014年
2015年
2016年
2017年
2018年
2019年
2020年
2021年
2022年
2023年
2024年
2025年
過去日記について
アクセス統計
サーバ一覧
サイトの情報合計:
本日: