特定のクラスメンバだけをfriendにしたい – プログラミング – Home

特定のクラスメンバだけをfriendに...
 
通知
すべてクリア

[解決済] 特定のクラスメンバだけをfriendにしたい

固定ページ 1 / 2

C++初心者
 C++初心者
(@C 初心者)
ゲスト
結合: 21年前
投稿: 30
Topic starter  

あるクラスで別のクラスをfriendとするとそのクラスの全メンバにアクセスできますが、
特定のメンバだけをfriendにする事はできるのでしょうか?

例えば、

#include <iostream>

using namespace std;

class A {
friend class B;
static void fa() { cout << A::fa() << endl; }
static void fb() { cout << A::fb() << endl; }
public:
};

class B {
public:
void Execute1() { A::fa(); }
void Execute2() { A::fb(); }
};

int main()
{
B ob;
ob.Execute1(); // OK
ob.Execute2(); // Errorにしたい

return 0;
}

上のコードで、当然class Bからclass Aの全メンバにアクセスできますが、
A::fa()はアクセスできて、A::fb()はアクセスできないようにしたい場合には
どうすればいいのでしょうか?


引用未解決
トピックタグ
επιστημη
 επιστημη
(@επιστημη)
ゲスト
結合: 22年前
投稿: 600
 

できなかったと思う。


返信引用
C++初心者
 C++初心者
(@C 初心者)
ゲスト
結合: 21年前
投稿: 30
Topic starter  

素早い回答、ありがとうございます。

できないのですか。
ちょっと残念ですが、グローバル関数を介すればそれっぽい事ができますね。

例えば、

#include <iostream>

using namespace std;

class A {
friend void Access();
static void fa() { cout << A::fa() << endl; }
static void fb() { cout << A::fb() << endl; }
public:
};

class B {
public:
void Execute() { Access(); }
};

void Access() { A::fa(); }

int main()
{
B ob;
ob.Execute();

return 0;
}

こんな感じに。
今気がついたんですけどね。


返信引用
REE
 REE
(@REE)
ゲスト
結合: 24年前
投稿: 240
 

その方法では、Access()はどこからも見えるので、
fa()だけpublicなのと、何も変わっていませんよ。


返信引用
C++初心者
 C++初心者
(@C 初心者)
ゲスト
結合: 21年前
投稿: 30
Topic starter  

確かに。
まあ、名前空間に封じて対処するしかないのでしょうね。
あくまで、それっぽい事ですから。


返信引用
επιστημη
 επιστημη
(@επιστημη)
ゲスト
結合: 22年前
投稿: 600
 

> まあ、名前空間に封じて対処するしかないのでしょうね。

え?


返信引用
dairygoods
 dairygoods
(@dairygoods)
ゲスト
結合: 23年前
投稿: 1421
 

こんなのは?

class SuperA {
friend class B;
static void fa() { cout << A::fa() << endl; }
};

class A : public SuperA {
static void fb() { cout << A::fb() << endl; }
};

class B
{
public:
void Execute1() { A::fa(); } // OK
void Execute2() { A::fb(); } // ERROR
};


返信引用
επιστημη
 επιστημη
(@επιστημη)
ゲスト
結合: 22年前
投稿: 600
 

なるほど、公開したいヤツを super に追い出す、か。
目的は達せられるけど、superA::fa()の実装が Aのメンバを必要としたら…
ってことがありうるので、適用できるかはビミョーなところ。


返信引用
C++初心者
 C++初心者
(@C 初心者)
ゲスト
結合: 21年前
投稿: 30
Topic starter  

おお、なるほど!!
まさにこれをやりたかったのです。

friendって継承されないんですね、忘れてました。
皆さん、ありがとうございました。


返信引用
monkey
 monkey
(@monkey)
ゲスト
結合: 21年前
投稿: 70
 

> superA::fa()の実装が Aのメンバを必要としたら…

このようなワケの分からんことに...

template < typename Sub >
class SuperA
{
friend class B;
static void fa()
{
cout << A::fa() << endl;
Sub::fb();
}
};

class A : public SuperA< A >
{
friend class SuperA< A >;
static void fb() { cout << A::fb() << endl; }
};


返信引用
επιστημη
 επιστημη
(@επιστημη)
ゲスト
結合: 22年前
投稿: 600
 

うーむ……小さな目的のために失うものの方が大きい気もするぞ。


返信引用
monkey
 monkey
(@monkey)
ゲスト
結合: 21年前
投稿: 70
 

同感です.あくまでも頭の体操ということで.
使ったことはないけど,ATLがこんな仕組み(ウィンドウの基本クラスがテンプレートに
なっていて,派生クラスを基本クラスのテンプレート引数に渡す)を使っていたような
気がします.


返信引用
C++初心者
 C++初心者
(@C 初心者)
ゲスト
結合: 21年前
投稿: 30
Topic starter  

アドバイスありがとうございます。

なぜこうしたくなったかといいますと・・・

AというクラスはBからしか生成できない、よってAのコンストラクタはprivateです。
そして生成関数 static A*A::Create() という関数を作りますが、これを呼ぶ事が
できるのはBというクラスの B::CreateA() という関数のみしにたい。
だけどAとBは継承関係にはありません。
そしてBからはAのprivateな関数にはアクセス不可能にしたい。(もちろんCreate()以外)

・・・といった状況だったのです。
始めからこう質問すれば良かったですね、説明不足で申し訳ないです。

で、結局A::Create()をpublicにしてB::CreateA()というAの生成関数以外からは
A::Create()を呼ばないように注意するのが一番だという気がします。

もし何かアドバイスがありましたらよろしくお願いします。(解決押しちゃったけど)


返信引用
monkey
 monkey
(@monkey)
ゲスト
結合: 21年前
投稿: 70
 

ネストかな...

#include <iostream>

class B
{
class A
{
A(){ std::cout << A::constructor << std::endl; }
void f(){ std::cout << A::f() << std::endl; }

public:
static A* create(){ return new A; }
~A(){ std::cout << A::destructor << std::endl; }
void g(){ std::cout << A::g() << std::endl; }
};

public:
void create_a()
{
A* p = A::create();
p->f(); // error
p->g(); // ok
delete p;
}
};

int main()
{
B b;
b.create_a();

B::A* p = B::A::create(); // error
delete p;
}


返信引用
C++初心者
 C++初心者
(@C 初心者)
ゲスト
結合: 21年前
投稿: 30
Topic starter  

おお、ネストですか。(やった事なかったです・・・)

ですが、それですとAのstaticな公開メンバにアクセス出来ませんよね?
Bにそれへのインターフェースを付ければいいのかな。

なるほど、参考になりました。
何回もありがとうございます。
これで本当の解決です!!

・・・早く初心者の域を脱したいです。


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

返信する

投稿者名

投稿者メールアドレス

タイトル *

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