環境
言語:c++11以降
コンパイラは問いません
質問
クラスAをpublic継承したクラスBを定義します
このままではBはAに暗黙にキャスト可能です
クラスAをいじらずに BからAへのアップキャストを禁止する方法はありますか
cpp
1 2struct A { 3 A() = default; 4 ~A() = default; 5 A(A&) = default; 6 A& operator=(A&) = default; 7 A(A&&) = default; 8 A& operator=(A&&) = default; 9 10public://関数 11 void a() {} 12 void b() {} 13 14}; 15 16struct B :public A { 17 18}; 19 20int main() { 21 B b; 22 A a; 23 24 b.a();//Aのメンバ関数は使いたい 25 26 a = b;//upcastを禁止したい 27}
試した方法
protected継承にして関数をusingで一つずつ使えるようにする
デメリット
- Aに関数が追加されたときにB側も変える必要がある
- 書くのがめんどくさい
- 視覚的に複雑に見える
cpp
1 2struct A { 3 A() = default; 4 ~A() = default; 5 A(A&) = default; 6 A& operator=(A&) = default; 7 A(A&&) = default; 8 A& operator=(A&&) = default; 9 10public://関数 11 void a() {} 12 void b() {} 13 /* 14 . 15 . 16 . 17 */ 18}; 19 20struct B :protected A { 21 using A::a; 22 using A::b; 23 /* 24 using A::c; 25 using A::d; 26 using A::e; 27 . 28 . 29 . 30 */ 31}; 32 33int main() { 34 B b; 35 A a; 36 37 b.a(); 38 //a = b;//禁止できた 39}
もっと簡潔に書く方法がないかと思い質問させていただきました
よろしくお願いいたします
追記
質問欄より
なぜ禁止したいのでしょうか?
次のようなことを考えていました
クラスAは他者のコードをライブラリとして使っているため いじりたくありません(ライセンスによっては編集できない場合もある)
そのクラスAにはcopy
move
コンストラクタがdefault
宣言されています
しかし、私はcopy
move
コンストラクタも使われたくありません
なので、継承してcopy
move
コンストラクタをdelete
宣言しました
誤ってアップキャストしてしまうと↑目的が達成できません
また、classAがvirtual
デストラクタでもないためclassBが解放されない事故も起きてしまうように思います
cpp
1 2struct A { 3 A() = default; 4 ~A() = default; 5 A(A&) = default; 6 A& operator=(A&) = default; 7 A(A&&) = default; 8 A& operator=(A&&) = default; 9 10public://関数 11 void a() {} 12 void b() {} 13}; 14 15//copy move を delete 16struct B : public A{ 17 B() = default; 18 ~B() = default; 19 B(B&) = delete; 20 B& operator=(B&) = delete; 21 B(B&&) = delete; 22 B& operator=(B&&) = delete; 23}; 24 25int main(){ 26 27 { 28 std::unique_ptr<A> test1 = std::make_unique<B>(); 29 }//B::~Bが呼ばれない 30 31 A* test2 = new B(); 32 delete test2;//B::~Bが呼ばれない 33} 34
よく考えたらアップキャストを禁止したところで抜け穴はありますね
回答欄より
is a関係の派生クラスではなく、has a関係のネストクラスを使うのはどうですか?
is aとhas aについてあまり理解していませんが、それとなく機能しそうです
ありがとうございます
cpp
1struct A { 2 A() = default; 3 ~A() = default; 4 A(A&) = default; 5 A& operator=(A&) = default; 6 A(A&&) = default; 7 A& operator=(A&&) = default; 8 9public://関数 10 void a() {} 11 void b() {} 12 13 14}; 15 16struct B { 17 B() = default; 18 ~B() = default; 19 B(B&) = delete; 20 B& operator=(B&) = delete; 21 B(B&&) = delete; 22 B& operator=(B&&) = delete; 23 24public: 25 A* operator ->() noexcept { 26 return &a; 27 } 28 29private: 30 A a{}; 31 32}; 33 34int main() { 35 B b; 36 b->a(); 37} 38

回答2件
あなたの回答
tips
プレビュー