MFC MDIプログラミングで、
Genericクラスで点、線、面クラスを作って、
オブジェクトを組み合わせて
3次元図形を作っています。

図形を削除する際、
delete演算子で各オブジェクトの
メモリ解放をプログラムしています。

例)
delete m_pLine;
delete m_pSurface;

しかしながら、これらポインタの中には、
アルゴリズム上、既にdeleteされているものもあるため、
既にdeleteしたオブジェクトを更に
deleteしようとして
実行時エラーを生じてしまいます。

deleteする前に、
当該ポインタが既にdeleteされているかどうか
判定する関数等あれば
if文で回避できると思うのですが、
何か良い方法がありますでしょうか?

よろしくお願いします。

A 回答 (4件)

if (m_pLine != NULL)


{
delete m_pLine;
m_pLine=NULL;
}

とすれば、どうでしょう
    • good
    • 1

結構嫌な問題ですね。


生成する前にNULLで初期化しておいて・・・・というのが
定石的な方法でしょうか。
deleteした後もポインタにNULLを入れておく、ということで。
その約束の上でなら、NULLかどうかの判定が出来ます。

それ以外によい方法があるなら・・・私が知りたいです(笑

他にもいくつか方法はありますが、どれもお勧め出来る方法じゃ
ありませんので・・・。
    • good
    • 0
この回答へのお礼

ご連絡が遅くなりましてすみません。

hohihohiさん、MAGIさん、selenityさん、hyde-laさん
昨年は、未熟な自分に
ご指導ありがとうございました。

さて、皆様のご指摘のおかげで、
問題が2つあることがわかり、
無事解決することができました。

1つは、同一ポインタの2重メモリ解放で
ポインタにNULL値を設定することで、
無事解決できました。

もう1つは、
2つ以上のポインタが同一の実体(アドレス)を
参照している場合
(2つの面が同一の辺を共有している場合等)で、

hohihohiさんのご指摘のとおり、
アルゴリズムに問題があり、
1つがdeleteされたら、
共有ポインタ全てにお知らせすることで、
解決することができました。

本当にありがとうございました。
本年もご指導よろしくお願い致します。

ポイントにつきましては、
MAGIさん,selenityさん、hyde-laさんの
3方につきましては、
同様のアドバイスでしたので、
最速のMAGIさんということでご了承願います。
(気持ち的にはみなさんに登録したいのですが。。。)

お礼日時:2001/01/04 11:49

簡単な回避方法としては、


delete実行直後に、変数にNULLを代入すれば良いと思います。
例)
if(m_pLine){
delete m_pLine;
m_pLine=NULL;
}
if(m_pSurface){
delete m_pSurface;
m_pSurface=NULL;
}
    • good
    • 0

それは、そもそもアルゴリズム的に間違えているような気がします。


zico さんがソフト開発に関してどの程度のレベルの方かわかりませんが、仮に初心者でしたら、この場合、明らかにプログラムの方針そのものが間違いなので、多重 delete しないような作りに書き直すべきです。
    • good
    • 0
この回答へのお礼

ご連絡が遅くなってすみません。
年末サーバーがダウンしてしまいまして。。。

アドバイスありがとうございました。
おかげさまで、NULL値設定とともにアルゴリズム改良によって
解決することができました。

本年もご指導よろしくお願いします。

お礼日時:2001/01/04 11:30

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人はこんなQ&Aも見ています

このQ&Aを見た人が検索しているワード

このQ&Aと関連する良く見られている質問

QC++でコンテナを扱う際の質問です。

C++でコンテナを扱う際の質問です。

確保されるメモリ位置が最後まで保証されているコンテナは存在するのかを知りたいです。

Vectorは連続性が保障されていることから間違いなくアドレスは変わると思うのですが、Deque、Listなどはどうか知りたいです。

固定されているならアドレスをMapのkeyのように扱えるかも?などと考えた次第です。

Dequeだと削除しないかぎり変わらないよ!などといった条件がある場合はそれも教えていただけると尚嬉しいです。

よろしくお願いします

Aベストアンサー

コンテナなどは、連続性といっても見かけの連続性だけを保証するのが普通です。

その意味からは、物理的なアドレスが固定されているかどうかは断言できません。
そういうわけで、コンテナの場合は、ポインタ経由ではなくて、イテレータ経由でアクセスするわけです。

ただ、deque は、[] をサポートしているので、

std::deque<int> que;

に対して、 que[0], que[1] などは、期待通りの動作をするはずです。(未確認)
残念ながら、list は、[] をサポートしていませんので、同じ記述はできません。

もともと、配列のレベルであっても、連続性は厳密には、

・ &a[n] - &a[m] が、n - m に等しくなる
・ ptr = &a[n] のとき、*(ptr + m) は、a[n + m] をポイントする

ということであって、あからさまに、物理的なメモリのアドレスは出てこないですから。
なので、ポインタ同士の減算も、「両方のポインタが同じ配列にあるか、一度に malloc() された同じ領域をポイントしている場合」しか、保証されていなかったりします。

コンテナなどは、連続性といっても見かけの連続性だけを保証するのが普通です。

その意味からは、物理的なアドレスが固定されているかどうかは断言できません。
そういうわけで、コンテナの場合は、ポインタ経由ではなくて、イテレータ経由でアクセスするわけです。

ただ、deque は、[] をサポートしているので、

std::deque<int> que;

に対して、 que[0], que[1] などは、期待通りの動作をするはずです。(未確認)
残念ながら、list は、[] をサポートしていませんので、同じ記述はできません。

もともと、...続きを読む

Q基本クラスポインタ = new 派生クラス[i];

基本クラスのポインタ変数pbaseを宣言し、new演算子にて派生クラスの配列を動的に確保して、pbaseに代入した場合、delete[] pbaseは上手く動作するのでしょうか。
(Aのデストラクタは仮想関数にしてあるとしておきます)

------ex-start------
class A {};
class b:public A{};

main()
{
  A * pbase
  pbase = new B[5];
  delete[] pbase
}
------ex-end------

例えば、
class Aは12バイト
class Bは20バイト
である場合、配列のサイズが違うのに、delete[]でちゃんと開放されるのでしょうか。
それともnew/deleteは確保したサイズをシンボル毎に記憶しているのでしょうか。
どうもこの辺が曖昧で実装する時にあやふやになってしまいます。どなたかお知恵をお貸しくださいませ。

Aベストアンサー

struct A { int x; virtual ~A() { cout << "~A: " << this << endl; } };
struct B: A { int y; ~B() { cout << "~B: " << this << endl; } };
B *b = new B[5];
A *a = b;
A *a2= a + 2;
a2->x = 1;
delete[] a;
これを素朴に考えると a2 は単純に a に 2 * sizeof(A) バイト足した場所(b[1] と b[2] の中間ぐらい?)を指すかもしれないです。a2->x = 1 は危険な感じがします。
delete [] が、配列の各要素のデストラクタに渡す this を求めるときに同様の失敗をするかもしれないです。

…と今日まで思っていましたが、実際やってみると delete[] で new B[5] が削除できてしまいました(VC++6.0)。不思議です。

QVisual C++ 6.0とVisual C++ 2005 についてですが・・・

Visual C++ 6.0でワークスペースと呼ばれていた物がVisual C++ 2005になるとソリューションと言う名前になったと聞きました。
また、Visual C++ 6.0で製作したファイルはVisual C++ 2005でも開けるけどVisual C++ 2005製作したファイルはVisual C++ 6.0では開けないと聞いたのですがVisual C++ 2005製作したファイルをVisual C++ 6.0でも開ける様に互換性を持たせる方法はありませんか?
学校と家で使っている環境が違うので互換性がもてれば両方で使えてとても便利になります。
御存知の方がいましたら御伝授お願いします。

Aベストアンサー

ソースファイルやヘッダファイル(拡張子CPP/C/H/HPPなど)はVisual C++ 6.0と2005で共用できるので、6.0用のプロジェクトファイル&ワークスペースと、2005用のプロジェクトファイル&ソリューションファイルを用意すれば両方の環境で開発を進めることができるでしょう。

但し、以下の点にご注意下さい。
・ソースファイルの追加や削除は両方のプロジェクトに対して行うこと。
・Visual C++6.0ではManaged C++が使えないのでManaged C++は使わないこと。
・MFCの仕様がだいぶ違うので、MFCも避けること。MFCを知り尽くしているのでしたらチャレンジはご自由に。
・C++コンパイラとしても若干仕様が違うので(for文内で定義された変数のスコープなど)、常に両方の環境でコンパイルできるか考えながら開発する必要があること。

Q親クラスのポインタ、クラスを指定しないポインタ

親クラス A (抽象メソッドX、Yの2つを持つ) と
子クラス B-1 (親はA、抽象メソッドX、Y、Zの3つを持つ)
子クラス B-2 (親はA、抽象メソッドX、Y、Wの3つを持つ)
のように、子クラスでポリモーフィズムを実現しているとき、

クラスC
  「実行時に、iniファイルに(1)と書かれていたら、B-1のクラスで実体化し、
  iniファイルに(2)と書かれていたら、B-2のクラスで実体化する」
 というクラスを作りたいです。

////////////////////////////////////////////////////////////////

質問(1)
その際、クラスCは、どうやってもZのメソッドや、Wのメソッドは書けない認識です。
(メソッド名もiniファイルから取るようにすれば別でしょうが。)
この認識であっていますでしょうか?

質問(2)
逆に、XとYについては、それぞれ挙動の違う処理を行わせることができる認識です。
(クラスCで、親クラスAのポインタ型の変数を用意しておき、
 そのポインタに、DLLのインスタンス化したものをいれておけば、
 メソッドXとYについては実行可能という認識です)

親クラス A (抽象メソッドX、Yの2つを持つ) と
子クラス B-1 (親はA、抽象メソッドX、Y、Zの3つを持つ)
子クラス B-2 (親はA、抽象メソッドX、Y、Wの3つを持つ)
のように、子クラスでポリモーフィズムを実現しているとき、

クラスC
  「実行時に、iniファイルに(1)と書かれていたら、B-1のクラスで実体化し、
  iniファイルに(2)と書かれていたら、B-2のクラスで実体化する」
 というクラスを作りたいです。

////////////////////////////////////////////////////////////////

質問(1)
その...続きを読む

Aベストアンサー

> その際、クラスCは、どうやってもZのメソッドや、Wのメソッドは書けない認識です。

dynamic_castでは解決にならんですか?

> 逆に、XとYについては、それぞれ挙動の違う処理を行わせることができる認識です。

こんなこと訊くまでもないでしょう。やってみりゃわかる。


#include <iostream>

using namespace std;

class A {
public:
virtual void x() =0;
virtual void y() =0;
};

class B1 : public A {
public:
virtual void x() { cout << "B1::x()\n"; }
virtual void y() { cout << "B1::y()\n"; }
virtual void z() { cout << "B1::z()\n"; }
};

class B2 : public A {
public:
virtual void x() { cout << "B2::x()\n"; }
virtual void y() { cout << "B2::y()\n"; }
virtual void w() { cout << "B2::w()\n"; }
};

class C {
public:
A* create(int n) {
A* result;
switch ( n ) {
case 1: result = new B1(); break;
case 2: result = new B2(); break;
default: result = nullptr; break;
}
return result;
}
};

void test(A* p) {
p->x();
p->y();
B1* p1 = dynamic_cast<B1*>(p);
if ( p1 ) p1->z();
B2* p2 = dynamic_cast<B2*>(p);
if ( p2 ) p2->w();
}

int main() {
C c;
A* p;
p = c.create(1);
test(p);
delete p;
p = c.create(2);
test(p);
delete p;
}

> その際、クラスCは、どうやってもZのメソッドや、Wのメソッドは書けない認識です。

dynamic_castでは解決にならんですか?

> 逆に、XとYについては、それぞれ挙動の違う処理を行わせることができる認識です。

こんなこと訊くまでもないでしょう。やってみりゃわかる。


#include <iostream>

using namespace std;

class A {
public:
virtual void x() =0;
virtual void y() =0;
};

class B1 : public A {
public:
virtual void x() { cout << "B1::x()\n"; }
virtual void y() { cout << "B1::y()...続きを読む

QCかC++どちらを覚えるべきですか?

初めまして。せいじと申します。よろしくお願いします。
プログラミング経験なしです。今30歳です。
遅すぎますが、これからC言語かC++言語をマスターしたいと思っています。
Windows 98 + Borland C++ Compiler 5.5
で勉強しようと思ってます。

Cの拡張されたものがC++だからC++を覚えようと思って、C++の本を買いました。
・新C++言語入門 ビギナー編 SOFTBANK Publishing 林 晴比古 著
・詳説C++             SOFTBANK Publishing 大城 正典 著
2冊ともまだ最初の方を読んで実践しただけです。

クラス、オブジェクト指向プログラミング等々が何なのか分かっていないのに、
C++をする意味があるのか、まずはCで十分ではないのか?
と思うようになってきました。

実際どうしたら良いのでしょう。
何も知らないならC++からでも良いのでしょうか。
違いが分からないならCで十分なのでしょうか。
みなさんの意見を聞かせてください。

よろしくお願いします。

初めまして。せいじと申します。よろしくお願いします。
プログラミング経験なしです。今30歳です。
遅すぎますが、これからC言語かC++言語をマスターしたいと思っています。
Windows 98 + Borland C++ Compiler 5.5
で勉強しようと思ってます。

Cの拡張されたものがC++だからC++を覚えようと思って、C++の本を買いました。
・新C++言語入門 ビギナー編 SOFTBANK Publishing 林 晴比古 著
・詳説C++             SOFTBANK Publishing 大城 正典 著
2冊ともまだ最初の方を読んで実...続きを読む

Aベストアンサー

seiji-h さん。こんにちわ。
プログラミングを今後主に何の目的で使いますか?

(1)仕事でC++が必要。
 頑張っておぼえましょう。

(2)文書データの加工など。。。
 今すぐPerl言語に切り替えましょう。

(3)趣味でWindowsアプリなどの作成を目指して。。
 そのままコツコツC++を続けていってください。

(4)歯ごたえのあるプログラミング言語を。。。
 そのままコツコツC++を続けていってください。

>実際どうしたら良いのでしょう。
>何も知らないならC++からでも良いのでしょうか。
どのようなことに興味をおぼえるかで、Cから始めるべきか、C++から始めるべきか
向き不向きがあります。

★簡潔な文法をもとに、ガリガリと自分の思うままに、プログラミングしたい。
とにかく自分で動くものを作りたいということなら、Cから始めるのが向いていると思われます。
★プログラミングすることよりも、プログラミング言語「自体」に興味があって、
一種の研究の対象と考えている場合は、C++の方が、おもしろおかしく学べると思います。

seiji-h さん。こんにちわ。
プログラミングを今後主に何の目的で使いますか?

(1)仕事でC++が必要。
 頑張っておぼえましょう。

(2)文書データの加工など。。。
 今すぐPerl言語に切り替えましょう。

(3)趣味でWindowsアプリなどの作成を目指して。。
 そのままコツコツC++を続けていってください。

(4)歯ごたえのあるプログラミング言語を。。。
 そのままコツコツC++を続けていってください。

>実際どうしたら良いのでしょう。
>何も知らないならC++からでも良いのでしょうか。
...続きを読む

Qnewされたポインタとdeleteされるポインタが…

いま私は、std::mapを使って、newされたポインタ(メモリの先頭アドレス)をkeyとして記録し、newされた場所のファイルや行番号、サイズ、何回目のnewか、などなどをvalueとして構造体にまとめて保存してデバッグなどに役立て、deleteされると同時にこの情報を破棄し、最後にすべて破棄されているかどうかを調べる(メモリリークのチェック)という機構を作っています。
ですが、keyとなっているメモリのアドレスは、多重継承や仮想継承とキャストの組み合わせ次第では、newされた時点のものとdeleteされる時点のもので異なっている場合があるため、情報を破棄することができず、行き詰ってしまいました。(無論、delete以外にも情報を引き出す際に影響が…)
deleteするポインタから、そのポインタがnewで作成されたときのメモリの先頭アドレスを求める方法はないでしょうか?

以下に問題の部分だけ抽出したようなコードを挙げます。

----------------

#include <stdio.h>

class CLS1{
public:
int x,y,z;
virtual ~CLS1(){}
};

class CLS2{
public:
int x,y;
virtual ~CLS2(){}
};

class CLS3:public CLS1, public CLS2{
public:
int x;
virtual ~CLS3(){}
};

void print(void* p){printf("%p\n",p);}

template<typename T>
T* create(T* p){
// ここで、たとえば 00854880 と記録されたとして…
print(p);
return p;
}

template<typename T>
void releace(T* p){
// ここでも 00854880 と記録されてほしいが、
// 00854890 と記録されてしまう。
// この場所で 00854880 と同じインスタンスであることを確かめる方法はないでしょうか?
print(p);
delete p;
}

int main(){
CLS2* x = create(new CLS3);
// 多重継承しているため、 00854890 と記録される。
print(x);
release(x);
return 0;
}

いま私は、std::mapを使って、newされたポインタ(メモリの先頭アドレス)をkeyとして記録し、newされた場所のファイルや行番号、サイズ、何回目のnewか、などなどをvalueとして構造体にまとめて保存してデバッグなどに役立て、deleteされると同時にこの情報を破棄し、最後にすべて破棄されているかどうかを調べる(メモリリークのチェック)という機構を作っています。
ですが、keyとなっているメモリのアドレスは、多重継承や仮想継承とキャストの組み合わせ次第では、newされた時点のものとdeleteされる時点のもの...続きを読む

Aベストアンサー

> あぁ、なるほど、int型とか仮想関数を持たないクラスのような非ポリモーフィックな型だったりするとdynamic_castが使えなくてコンパイルエラーを起こすということですか…
> ほかにだめな場合はありますか?
> また、これらを何らかの方法でふるいにかけることってできますかね?

boostを使ってもよいのなら、

#include <boost/type_traits.hpp>

template <class T, bool = boost::is_polymorphic<T>::value>
struct C
{
static void *foo(T* p) { return static_cast<void*>(p); }
};
template <class T>
struct C<T,true>
{
static void *foo(T* p) { return dynamic_cast<void*>(p); }
};
template<typename T>
void releace(T* p){
print(C<T>::foo(p));
delete p;
}

> あぁ、なるほど、int型とか仮想関数を持たないクラスのような非ポリモーフィックな型だったりするとdynamic_castが使えなくてコンパイルエラーを起こすということですか…
> ほかにだめな場合はありますか?
> また、これらを何らかの方法でふるいにかけることってできますかね?

boostを使ってもよいのなら、

#include <boost/type_traits.hpp>

template <class T, bool = boost::is_polymorphic<T>::value>
struct C
{
static void *foo(T* p) { return static_cast<void*>(p); }
};
templat...続きを読む

QVisual C++を使用するには,C++の知識は必要?

Visual C++ を使用する必要が生じたのですが,C言語の知識しかなく,
VC++を使用するにあたり,新たにC++を勉強しなければならないか分かりません。
C++を勉強してから,VC++を勉強し始めるべきなのでしょうか?
また,もしC++の勉強をしなければならない場合,使用する参考書として「独習C++」を考えているのですが,この参考書で事足りるでしょうか?
回答よろしくお願いします。

Aベストアンサー

ANo.1の方に同感です。

私はMS-DOSでのC言語からVC++へジャンプしました。

VC++を理解するということは
 1.C++という言語
 2.windowsOS,API
 3.MFC
を理解するということです。

私のとっかかりの本は、3冊のシリーズで
 1.Windowsプログラミングについて
 2.C++について
 3.MFCについて(だった思う)
に分かれており、C言語の知識とwindowsのアプリを触った経験があれば順を追って素直に理解できるものでした。
#処分してしまったので正しい書籍名はわかりませんが、クリーム色のカバーでした。

ただ、これはあくまで入門書で、その後C++に関する本、MFCに関する本、WIN32APIに関する何冊か読まないと、やはり仕事はできません。

Q互いのクラスで互いのクラスのポインタを持ち合う方法

◆hoge.h
#pragma once
#include "fuga.h"

class Choge{
protected:
 Cfuga *fuga;
public:
 Choge( void ){ fuga=new hoge(this); }
 ~Choge();
};

◆fuga.h
#pragma once
#include "hoge.h"

class Cfuga{
protected:
 Choge *hoge;
public:
 Cfuga( hoge *h ){ hoge=h; }
 ~Cfuga();
};

このように互いのポインタを持ち合うようなクラスを作りたいのですが、
下記のようなエラーが出てどうにもうまくいきません。

c:\...\hoge.h(5) : error C2143: 構文エラー : ';' が '*' の前にありません。
c:\...\hoge.h(5) : error C4430: 型指定子がありません - int と仮定しました。メモ: C++ は int を既定値としてサポートしていません
c:\...\hoge.h(5) : error C4430: 型指定子がありません - int と仮定しました。メモ: C++ は int を既定値としてサポートしていません

環境はVisualC++2005(ExpressEdition)、WindowsXPです。
どうすれば実現できるでしょうか?

◆hoge.h
#pragma once
#include "fuga.h"

class Choge{
protected:
 Cfuga *fuga;
public:
 Choge( void ){ fuga=new hoge(this); }
 ~Choge();
};

◆fuga.h
#pragma once
#include "hoge.h"

class Cfuga{
protected:
 Choge *hoge;
public:
 Cfuga( hoge *h ){ hoge=h; }
 ~Cfuga();
};

このように互いのポインタを持ち合うようなクラスを作りたいのですが、
下記のようなエラーが出てどうにもうまくいきません。

c:\...\hoge.h(5) : error C2143: 構文エラー : ';' が '*'...続きを読む

Aベストアンサー

ヘッダファイルをインクルードするのではなく、先行宣言だけにしましょう。

class Choge;

class Cfuga;

QC/C++でアプリ開発

C/C++でアプリ開発

いまどきC++でアプリ開発なんてしないのででしょうか。
C/C++を使うのは組み込み分野とかぐらいなんでしょうか?
もし新卒の大学生がC/C++でアプリ開発するならどういう会社に入ればよいでしょうか?

Aベストアンサー

ソフトウェアハウスとかなら今でもC言語が必要になる案件は多いです
Windows向けソフトウェアの受託とか、Linuxアプリケーションとか。

ただ、C言語でそれなりの結果を出している
というわけでは無いのでしたら、
無理してC言語にこだわらない方がいいかもしれません。
Cで開発するだけの自信があるのでしたら、
それ以外の言語の仕事も十分に出来ますし、
そっちの方が仕事が捕まえやすいというのもあります。
それにC言語の仕様の多さは他の言語には類を見ないくらいに大きいですから、
他の言語の仕様を覚えてからでも、十分に役立たせることが出来る。

Q基本クラスのポインタから、特定の派生クラスのメンバ変数を変更する方法?

VC++でプログラミングをしています。
A(基本クラス)
A1, A2, A3, ...(派生クラス)
を作成しました。A1,A2,A3, ...は、Aの派生クラスです。

このとき、基本クラスAのポインタから、特定の派生クラスにのみ存在するメンバ変数m_dataのみ変更したいのですが、存在するかどうかをどのように判定して、値を変更すれば良いでしょうか?

できれば、下記のような構造でループできるとありがたいです。

A* a[100]
(その後、a[100]に、派生クラスA1,A2,A3,..を割り当て、
 それらが、混在しているとします。)

for(i=0 ; i<100 ; i++){
if(a[i]->m_dataが存在する場合){ (2)
  a[i]->Set_m_data("m_dataの新しい値") (1)
 }
}

(1)は、a[i]->m_data = "m_dataの新しい値"
でも良いです。

現状では、m_dataがメンバでない派生クラスがあるので、
(2)のif文の判定自体ができず困っています。

よろしく御願いします。

VC++でプログラミングをしています。
A(基本クラス)
A1, A2, A3, ...(派生クラス)
を作成しました。A1,A2,A3, ...は、Aの派生クラスです。

このとき、基本クラスAのポインタから、特定の派生クラスにのみ存在するメンバ変数m_dataのみ変更したいのですが、存在するかどうかをどのように判定して、値を変更すれば良いでしょうか?

できれば、下記のような構造でループできるとありがたいです。

A* a[100]
(その後、a[100]に、派生クラスA1,A2,A3,..を割り当て、
 それらが、混在しているとし...続きを読む

Aベストアンサー

言語仕様的はメンバ変数の存在を確認する方法は無いです。
(処理系依存でも良いならば全く無いわけではありませんが…)

よって別のアプローチで
(1)仮装関数を利用して別個に処理させる
class A{
public:
   virtual Set_m_data(M_DATA &Adata){
      //何も入れない。空の処理
   }
};

class A1{ //メンバ無し
public:
   //何も作らない
};

class A2{ //メンバ有り
private:
   M_DATA m_data;
public:
   virtual Set_m_data(M_DATA &Adata){
      m_data = Adata;
   }
};
//代入処理
for(i=0 ; i<100 ; i++){
   a[i]->Set_m_data(m_dataの新しい値);//チェックする必要もない
}


(2)基底クラスAにm_data型のポインタを用意してそれで判別
class A{
public:
   M_DATA *pm_data:
   A(){//コンストラクタ
      pm_data = NULL; //NULLならばデータ無し
   }
};

class A1{ //メンバ無し
public:
   //何も作らない
};

class A2{ //メンバ有り
private:
   M_DATA m_data;
public:
   A2(){//コンストラクタ
      pm_data = &m_data; //NULLでない場合はデータ有り
   }
};


//代入処理
for(i=0 ; i<100 ; i++){
   if(a[i]->pm_data){//ここがNULLならばメンバ無しと判定できる
      *(a[i]->pm_data) = m_dataの新しい値; //そのまま代入も可能
   }
}

言語仕様的はメンバ変数の存在を確認する方法は無いです。
(処理系依存でも良いならば全く無いわけではありませんが…)

よって別のアプローチで
(1)仮装関数を利用して別個に処理させる
class A{
public:
   virtual Set_m_data(M_DATA &Adata){
      //何も入れない。空の処理
   }
};

class A1{ //メンバ無し
public:
   //何も作らない
};

class A2{ //メンバ有り
private:
   M_DATA m_data;
public:
   virtual Set_m_data(M_DATA &Adata){
      m_d...続きを読む


このQ&Aを見た人がよく見るQ&A

人気Q&Aランキング