• ベストアンサー

privateデストラクタを持つクラスの拡張

C++でprivateなデストラクタを持つクラスを拡張してサブクラスを作る方法はありますか?

質問者が選んだベストアンサー

  • ベストアンサー
  • jacta
  • ベストアンサー率26% (845/3158)
回答No.4

可能かどうかという意味では可能です。 ただし、オブジェクトを解体することは原則としてできなくなります。 「原則として」というからには、例外的な事例もあるわけですが... class A { private:  ~A();  friend class B; }; class B : public A { }; であれば、Bは普通に使えます。この方法は、Aの派生クラスとして、B以外は作れないように制限するのに、もしかすると有効かもしれません(やったことは無いので知りません)。 あるいは、 struct xxx_traits {  static const int xxx_value;  static void func(); private:  ~xxx_traits(); }; struct yyy_traits : xxx_traits {  static void func(); }; のように、そもそもオブジェクトを作らないクラスであれば、間違ってオブジェクトを作らないように、セマンティックスを強制する意味で、このようにすることもよいかもしれません(やはり、やったことなし)。

bobviv
質問者

お礼

 回答有難うございます。  親クラスを変更することができる場合なら、確かにfriendにすればprivateデストラクタにアクセスできそうですね。それからインスタンスを作らないクラスの場合は害はなさそうです。  参考になりました。有難うございました。

その他の回答 (3)

回答No.3

訂正です。 大嘘を書いていたようです。 以下に書いた方法では、サブクラスを作ることはできませんでした。 サブクラスに明示的にデストラクタを書くと、その時点でアウトですし、サブクラスにデストラクタを書かなくても、コンパイラが暗黙のデストラクタを生成するので、その時点でアウトになってしまうようです。 失礼。

bobviv
質問者

お礼

 そうですね。自分のコードでも、サブクラスのデストラクタ冒頭でコンパイルエラーが出ていたような気がします。  回答有難うございました。

回答No.2

補足です。 この方法は、特殊メモリ管理をしているクラスライブラリで、ユーザに delete を使われては困るという事情があって、必ず、クラスライブラリ専用のデストラクタを呼び出して欲しいという意図で、使われていたのを見たような気がします。 operator new() はあるけど、operetor delete() はないので、operator delete() もどきの使い方だったと思います。

回答No.1

外部からデストラクタが呼び出せないだけなので、デストラクタを呼び出さなければ、可能です。 具体的には、まず、インスタンスの生成は、new を使った動的割当になります。静的に生成すると、暗黙にデストラクタが呼ばれてしまいますから。 デストラクタを呼び出すべき場面では、基底クラスの static メンバとして定義した、デストラクト用の関数を呼び出すことになります。 この関数で、(おそらく)何か特殊な処理をして、最終的に、基底クラスのデストラクタを呼び出すということで、動作は可能だと思います。

関連するQ&A

  • C++のクラスの仮想デストラクタについて

    C++のクラスの仮想デストラクタについて教えてください。 デストラクタは、クラスの名前の前にチルダを付けたものが名前になりますが、とあるクラスの継承クラスは、その親クラスとクラス名が違うので、デストラクタの名前も親クラスのものとは別になる。つまり。継承関係のあるクラスでもデストラクタはオーバーライドせず、各クラス毎に別の名前で存在する、ということになると思います。 ですので http://wisdom.sakura.ne.jp/programming/cpp/cpp31.html このページの下部にあるように、「デストラクタは、派生クラスから基本クラスへ向かって順番に呼び出される」というのもなんとなく合点が行きます。 しかし、仮想デストラクタというものがあることを知りました。 上記のようにデストラクタは継承関係のあるクラス間でも、それぞれクラス毎に作ればよいと思っていましたが、子クラスの方でオーバーライドする必要がある場合があるのでしょうか。あるとすれば、それはどんな場合なのでしょうか。 また、上記のURLでは、「C++ 言語のデストラクタはオーバーライドを行いません」と書いてあり、なんだかよく分からなくなってきました。仮想デストラクタというものが存在するのに? どなたか詳しい方いらっしゃいましたらご教示頂けると幸いです。

  • PHPでサブクラスからスーパクラスのprivate

    メンバにアクセスできる件について PHPでスーパークラスで定義したprivateのメンバにサブクラスからアクセスできる件について 質問です。 class TestClass { private $value01 = "スーパークラスの private メンバ"; public function testMethod01 () { print "スーパークラスのパブリックメソッド"; print "<h1>{$this->value01}</h1>"; } protected function testMethod02(){ print "スーパークラスの protected メソッド"; } private function testMethod03(){ print "スーパークラスの private メソッド"; } public function getMethodList(){ print_r(get_class_methods($this)); } } class ExClass extends TestClass{ private $value01 = "サブクラスの private メンバ"; } $obj = new ExClass(); $obj-> testMethod01(); と上記のようにサブクラスのインスタンスから継承したpublicなメソッド testMethod01()を実行すると スーパークラスのprivateなプロパティにアクセスできてしまいます。 これってどういうことでしょうか?privateメンバってそのクラスの中からだけしかアクセスできませんよね? 上記では、サブクラスからアクセスしているような状態にみえますがどういうことでしょうか? ご教授御願い致します。

    • ベストアンサー
    • PHP
  • C++ Vectorのデストラクタ

    C++ Vectorのデストラクタ boost::any型のVectorに自作クラスをpush_backで入れると、なぜかその自作クラスのデストラクタが呼ばれてしまって困っています。 またそのクラスの関数を実行すると同じようにデストラクタが呼ばれてしまいます。 

  • コンストラクタ・デストラクタ

    プログラミング言語はC++ C++を触り始めたばかりの素人です。 コンストラクタとデストラクタについて質問です。 下記に参考にしているウェブページから簡潔にしてコードを書いてみました。 コンストラクタ、デストラクタの中はそれぞれに、○○が呼び出されましたと書いてあるだけでよく分からなかったので別のウェブページを見たら コンストラクタは Sample::Sample(){ n=0; } みたいな例があったのですが、このように変数に予め何かの値を代入しておくという事で合ってますか? デストラクタは理解できていません。 下記の例では、どのような処理を書けばいいのでしょうか? #include<iostream> using namespace std; class Sample { private: int n; public: void Show(); Sample(); ~Sample(); }; void Sample::Show() { cout << n << endl; } Sample::Sample() { // n=0; std::cout << "コンストラクタが呼び出されました" << std::endl; } Sample::~Sample() { // どんな処理? std::cout << "デストラクタが呼び出されました" << endl; } main() { Sample sample; sample.Show(); return 0; } 実行結果 コンストラクタが呼び出されました 1     ←コンストラクタ関数内の//を削除で0になることは確認 デストラクタが呼び出されました

  • C++のデストラクタについて

    クラスAの変数Xをクラス外から変更した際に、クラスAのデストラクタに行くのですが、それは正しい処理なのでしょうか? 変数の変更はDXUTSetCallbackKeyboardでキーを押したときに変更されるようになっています。

  • [PHP] デストラクタについて教えて下さい

    あるPHPの入門書にデストラクタについての解説があります。 *デストラクタ 「コンストラクタとは反対に、オブジェクトが破棄されるタイミングで実行されるのがデストラクタです。名前は __destructに固定されている。 デストラクタには、クラスの中で使用したリソースを破棄するなど、主に終了するときの処理を記述するのが一般的です。」 とあります。 以下のような記述をしました。(person.php) <?php class Person{ public $lastName; public $firstName;  public function __construct($lastName, $firstName){ $this->firstName = $firstName; $this->lastName = $lastName; } public function show(){ print "<p>私の名前は {$this->lastName} {$this->firstName}です。</p>"; } public function __destruct(){ print "<p>インスタンスが破棄されました。<p>";  } } ?> 上の記述をインスタンス化する記述です。(instancne.php) <?php require_once('person.php'); $p = new Person('田中', '幸太郎'); $p->show(); ?> <表示結果> 私の名前は 田中 幸太郎です。 インスタンスが破棄されました。 となります。試しにもうひとつインスタンスを追加します。 <?php require_once('person.php'); $p = new Person('田中', '幸太郎'); $p->show(); $p1 = new Person('鈴木', '京子'); $p1->show(); ?> <表示結果> 私の名前は 田中 幸太郎です。 私の名前は 鈴木 京子です。 インスタンスが破棄されました。 インスタンスが破棄されました。 説明にある、 「オブジェクトが破棄されるタイミングで実行されるのがデストラクタです。」 「デストラクタには、クラスの中で使用したリソースを破棄するなど、主に終了するときの処理を記述するのが一般的です。」 これらの意味がわかりません。 コンストラクタの 「new 演算子によってインスタンス化されるタイミングで実行される」 「プロパティの初期化」 などの意味は理解できているつもりです。 デストラクタを使うと「オブジェクトが破棄される」、「クラスの中で使用したリソースを破棄する」と ありますが、『一度インスタンスを作るとクラス内のリソースが破棄されるのかな?』と思い ためしにもう一つインスタンスを作成しました。上記の通り問題なく使えています。 膨大な記述になると、クラス、この場合は 「class Person」」は再利用出来なくすると言った意味になるのでしょうか? 他の教材やネットで検索してみたりしたのですが、イメージがつかめません。 以下のPHP公式のサイトから考えてみると、クラス内で参照できるものがなければ、コールされるという風に解釈できるかもしれませんが、意味がわかりません。 デストラクタ(__destruct)はコンストラクタ(__construct)の反対というように記述されているものもありますが余計に意味が分かりません。 初学者にもわかるようにデストラクタについて教えてもらえないでしょうか? またどういうケースで利用するのかもよく分かりません。 そのあたりも併せて教えて下さい。 宜しくお願いいたいます。 (参考) デストラクタ __destruct(): void PHP には、C++ のような他のオブジェクト指向言語に似たデストラクタの概念があります。 デストラクタメソッドは、 特定のオブジェクトを参照するリファレンスがひとつもなくなったときにコールされます。 あるいは、スクリプトの終了時にも順不同でコールされます。 https://www.php.net/manual/ja/language.oop5.decon.php

    • ベストアンサー
    • PHP
  • C#デストラクタが走る理由がわからない(初心者)

    WPF C# アプリを初めて組んでいます。 MainWindowクラスで、publicなクラス変数配列(myclass)を定義し、 MainWindowのコンストラクタ(もしくはLoadedイベント)で、上記クラス変数にインスタンスを生成しています。 そのインスタンスを、MainWindows内のコントロールイベント(Button_Click)で参照しようとするとNullとなっておりました。 MainWindowのコンストラクタ(もしくはLoadedイベント)完了後に、デストラクトが走っているようです。 どこからも参照されていなければGCが走りデストラクタされるのはわかるのですが、 この場合、MainWindowクラスのメンバにクラス変数を追加し、そこにインスタンスを生成しています。よって、MainWindow(つまりアプリが)が終了するまでインスタンスが参照されているため、 デストラクタが走らないのではないかと考えておりました。 ですが、上記の通り、MainWindowのコンストラクタ(もしくはLoadedイベント)後には、MyClassデストラクタが走ってしまいます。この辺を教えていただけないでしょうか。 また、下記のように、Clickでインスタンスを参照するにはどうすればよいでしょうか。 public partial class MainWindow : Window {     MYClass []myclass;     public MainWindow()     {         InitializeComponent();         //ファイル読み込み(記載省略)         for(i=0; i<ファイル読み込み数;i++)         {             myclass[i] = new myclass(ファイル読み込みデータ);         }     }     private void Button_Click(object sender, RoutedEventArgs e)     {         for(int i=0;i<myclass.Length;i++) ←ここに来る前にすでにMyClassのデストラクタが走っており、nullとなっている         {             data = myclass[i].data;         }     } }

  • クラスの消滅時に処理をさせたいのですが

    C++のデストラクタのように、クラスの解放時に決まった処理をさせる方法はありませんでしょうか? よろしくお願いします。

    • ベストアンサー
    • Java
  • 修飾子 private protected

    Java での話です。 自分自身とサブクラスからのみアクセスできる変数は作成することはできないのでしょうか。修飾子 private protected の組み合わせは廃止されたようなのですが。 C++ だと、protectedで良かったと思うのですが、Java では同一パッケージからアクセスできるので戸惑ってしまいました。

    • ベストアンサー
    • Java
  • デストラクタについて

     C++初心者です。 delete [] tt ; でデストラクタが要素数だけ実行されるのは 確認しています。 ところがその実行後に、例えば、 cout << tt[3].test() << endl ; としますと、ちゃんと表示されます。 消滅したはずのオブジェクトが使えるのはど うしてでしょうか? どなたかお教え願えませんでしょうか。 どうぞよろしくお願いします。

専門家に質問してみよう