被通告扼杀的朋友功能包括
Friend function massacred by circular includes
Class A
是 class B
.
实例的唯一实例化器和容器
因此,将 class B
的构造函数设为私有似乎是个好主意,并且仅由 class B
中声明的友元函数调用,并且在 class A
.
中定义
文件A.h(编辑:包含在class B 中定义的枚举)
#ifndef A_H
#define A_H
#include "B.h"
using namespace std;
class A
{ public:
A();
shared_ptr<B> CreateBInstance( const B::ENUM_STANDARD_COLORS );
shared_ptr<B> CreateBInstance( const string ); // Custom color
private:
unique_ptr<map<int, shared_ptr<B>>> UPTR__BInstancesMap;
}
#endif
文件B.h(编辑:包含在class B 中定义的枚举)
#ifndef B_H
#define B_H
#include "A.h" // Causes chaos
using namespace std;
class B
{ public:
enum class ENUM_STANDARD_COLORS : unsigned int
{ ... // ~70 standard colors
};
private:
B();
friend
shared_ptr<B> A::CreateBInstance( const ENUM_STANDARD_COLORS );
friend
shared_ptr<B> A::CreateBInstance( const string ); // Custom color
}
#endif
Class A
需要 class B
的完整声明 (#include) for shared_ptr<B>
.
Class B
需要为友元函数声明一些 class A
。
一个简单的前向声明导致错误:
invalid use of incomplete type 'struc A'
在友元函数声明处。
完整声明 (#include) 更糟糕:
error: prototype for 'std::shared_ptr A::CreateInstance()' does not
match any in class 'A'
(但确实如此!)在友元函数声明处。
而且,因为 class B
现在坏了:
error: 'B' was not declared in this scope
error: template argument 1 is invalid
出现在 class A
以及 classes F
和 G
中每次提到 B
(等.) 其中#include class B
供自己使用 shared_ptr<B>
.
而且,因为 classes F
和 G
现在也被破坏了:
error: 'F' was not declared in this scope
error: template argument 1 is invalid>
error: 'G' was not declared in this scope
error: template argument 1 is invalid
出现在 class A
中每次提到 F
和 G
时。
不幸的是,包含守卫不会阻止循环包含。
有没有办法让这个好友功能起作用?我从来没有一次犯过这么多错误!
在A头文件中,你可以简单地告诉编译器存在一个类型B,它需要在链接时寻找它。为此,请替换
#include "B.h"
来自
class B;
Class A
requires a full declaration (#include) of class B
for shared_ptr<B>
.
不,前向声明在 A.h
中就足够了。 shared_ptr
(and unique_ptr
) 不需要 class B
是 return 类型声明的完整类型 [1] 和 class 数据成员声明。
文件A.h
#ifndef A_H
#define A_H
class B; // forward declaration
using namespace std;
class A
{ public:
A();
shared_ptr<B> CreateBInstance();
private:
unique_ptr<map<int, shared_ptr<B>>> UPTR__BInstancesMap;
};
#endif
[1] "regular" 类型 T
不是 shared_ptr
.
也是如此
让 class A 成为 class B 的朋友消除了循环包含(如上面 songyuanyao 的回答下的评论中所述),但我不喜欢给 A 太多访问 B 的权限。
我想我想出了一个更好的方法,使用继承。如果这个 friend-limited-by-inheritance 工厂模式有名字,那会很高兴。否则很高兴知道我在这里是不是在玩火。
文件A.h
#ifndef A_H
#define A_H
#include "B.h" // The more compelling reason for including B.h is that
// classes A thru Z comprise a static library, requiring
// only the inclusion of A.h to be used. B.h through Z.h
// must be included directly or indirectly in A.h so that
// the caller knows all of the library's public functions.
using namespace std // Makes these examples easier to read.
class A
{ public:
A();
shared_ptr<B> CreateBInstance( const B::ENUM_STANDARD_COLORS );
shared_ptr<B> CreateBInstance( const string ); // Custom color
private:
// Please excuse my standards-defying variable names
unique_ptr<map<int, shared_ptr<B>>> UPTR__BInstancesMap;
}
#endif
文件A.cpp
#include "A.h"
#include "BFactory.h"
...
shared_ptr<B> A::CreateBInstance( const B::ENUM_STANDARD_COLORS enum__StandardColor )
{ unsigned int uint__BInstancesMapIndex = UPTR__BInstancesMap->size();
shared_ptr<B> sptr__BInstance = BFactory::CreateBInstance( uint__BInstancesMapIndex, enum__StandardColor );
UPTR__BInstancesMap->insert( uint__BInstancesMapIndex, sptr__BInstance );
return sptr__BInstance;
}
shared_ptr<B> A::CreateBInstance( const string str___CustomColor )
{ unsigned int uint__BInstancesMapIndex = UPTR__BInstancesMap->size();
shared_ptr<B> sptr__BInstance = BFactory::CreateBInstance( uint__BInstancesMapIndex, str___CustomColor );
UPTR__BInstancesMap->insert( uint__BInstancesMapIndex, sptr__BInstance );
return sptr__BInstance;
}
...
文件B.h
#ifndef B_H
#define B_H
using namespace std // Makes these examples easier to read.
class B
{ public:
enum class ENUM_STANDARD_COLORS : unsigned int
{ ... // ~70 standard colors
};
// virtual // BFactory cannot be instantiated; it needs no destructor
~B();
protected:
static unique_ptr<B> CreateBInstance( const unsigned int, const ENUM_STANDARD_COLORS );
static unique_ptr<B> CreateBInstance( const unsigned int, const string ); // Custom color
private:
B( const unsigned int ); // Eliminates default constructor, therefore BFactory cannot
// call B::B(); therefore the compiler does not generate
// BFactory::BFactory(); therefore BFactory (and BFactory.o)
// is empty; it doesn't even need a cpp file.
}
#endif
文件B.cpp
#include "B.h"
...
unique_ptr<B> B::CreateBInstance( const unsigned int uint__BInstancesMapIndex, const ENUM_STANDARD_COLORS enum__StandardColor )
{ unique_ptr<B> uptr__BInstance = unique_ptr<B>( new B( uint__BInstancesMapIndex ) );
uptr__BInstance->SetColor( enum__StandardColor );
return uptr__BInstance;
}
unique_ptr<B> B::CreateBInstance( const unsigned int uint__BInstancesMapIndex, const string str___CustomColor )
{ unique_ptr<B> uptr__BInstance = unique_ptr<B>( new B( uint__BInstancesMapIndex ) );
uptr__BInstance->SetColor( str___CustomColor );
return uptr_BInstance;
}
...
文件BFactory.h
#ifndef BFactory_H
#define BFactory_H
#include "B.h"
class BFactory : private B // Make sure anything inherited from B becomes private.
{ friend class A // Friend declaration moved from class B.
};
#endif
更改摘要:
1) Class A不再是class B的好友
2) Class B 的工厂函数是受保护的,所以 BFactory 将继承它们,并且是静态的,这样我们就不需要 BFactory 的实例来调用它们。
3) Class BFactory 是 B 的空子class,没有构造函数、析构函数或局部成员;它只是继承了 B 的工厂函数,并将 class A 声明为友元。
4) Class A 现在调用BFactory 中的静态函数来获取B 的实例,而不是调用B 中的私有函数。
结果是只有 Class A 可以访问 class B 的静态工厂函数,而 class BFactory 不能用于其他任何事情——据我所知.
Class A
是 class B
.
因此,将 class B
的构造函数设为私有似乎是个好主意,并且仅由 class B
中声明的友元函数调用,并且在 class A
.
文件A.h(编辑:包含在class B 中定义的枚举)
#ifndef A_H
#define A_H
#include "B.h"
using namespace std;
class A
{ public:
A();
shared_ptr<B> CreateBInstance( const B::ENUM_STANDARD_COLORS );
shared_ptr<B> CreateBInstance( const string ); // Custom color
private:
unique_ptr<map<int, shared_ptr<B>>> UPTR__BInstancesMap;
}
#endif
文件B.h(编辑:包含在class B 中定义的枚举)
#ifndef B_H
#define B_H
#include "A.h" // Causes chaos
using namespace std;
class B
{ public:
enum class ENUM_STANDARD_COLORS : unsigned int
{ ... // ~70 standard colors
};
private:
B();
friend
shared_ptr<B> A::CreateBInstance( const ENUM_STANDARD_COLORS );
friend
shared_ptr<B> A::CreateBInstance( const string ); // Custom color
}
#endif
Class A
需要 class B
的完整声明 (#include) for shared_ptr<B>
.
Class B
需要为友元函数声明一些 class A
。
一个简单的前向声明导致错误:
invalid use of incomplete type 'struc A'
在友元函数声明处。
完整声明 (#include) 更糟糕:
error: prototype for 'std::shared_ptr A::CreateInstance()' does not match any in class 'A'
(但确实如此!)在友元函数声明处。
而且,因为 class B
现在坏了:
error: 'B' was not declared in this scope
error: template argument 1 is invalid
出现在 class A
以及 classes F
和 G
中每次提到 B
(等.) 其中#include class B
供自己使用 shared_ptr<B>
.
而且,因为 classes F
和 G
现在也被破坏了:
error: 'F' was not declared in this scope
error: template argument 1 is invalid>
error: 'G' was not declared in this scope
error: template argument 1 is invalid
出现在 class A
中每次提到 F
和 G
时。
不幸的是,包含守卫不会阻止循环包含。
有没有办法让这个好友功能起作用?我从来没有一次犯过这么多错误!
在A头文件中,你可以简单地告诉编译器存在一个类型B,它需要在链接时寻找它。为此,请替换
#include "B.h"
来自
class B;
Class
A
requires a full declaration (#include) of classB
forshared_ptr<B>
.
不,前向声明在 A.h
中就足够了。 shared_ptr
(and unique_ptr
) 不需要 class B
是 return 类型声明的完整类型 [1] 和 class 数据成员声明。
文件A.h
#ifndef A_H
#define A_H
class B; // forward declaration
using namespace std;
class A
{ public:
A();
shared_ptr<B> CreateBInstance();
private:
unique_ptr<map<int, shared_ptr<B>>> UPTR__BInstancesMap;
};
#endif
[1] "regular" 类型 T
不是 shared_ptr
.
让 class A 成为 class B 的朋友消除了循环包含(如上面 songyuanyao 的回答下的评论中所述),但我不喜欢给 A 太多访问 B 的权限。
我想我想出了一个更好的方法,使用继承。如果这个 friend-limited-by-inheritance 工厂模式有名字,那会很高兴。否则很高兴知道我在这里是不是在玩火。
文件A.h
#ifndef A_H
#define A_H
#include "B.h" // The more compelling reason for including B.h is that
// classes A thru Z comprise a static library, requiring
// only the inclusion of A.h to be used. B.h through Z.h
// must be included directly or indirectly in A.h so that
// the caller knows all of the library's public functions.
using namespace std // Makes these examples easier to read.
class A
{ public:
A();
shared_ptr<B> CreateBInstance( const B::ENUM_STANDARD_COLORS );
shared_ptr<B> CreateBInstance( const string ); // Custom color
private:
// Please excuse my standards-defying variable names
unique_ptr<map<int, shared_ptr<B>>> UPTR__BInstancesMap;
}
#endif
文件A.cpp
#include "A.h"
#include "BFactory.h"
...
shared_ptr<B> A::CreateBInstance( const B::ENUM_STANDARD_COLORS enum__StandardColor )
{ unsigned int uint__BInstancesMapIndex = UPTR__BInstancesMap->size();
shared_ptr<B> sptr__BInstance = BFactory::CreateBInstance( uint__BInstancesMapIndex, enum__StandardColor );
UPTR__BInstancesMap->insert( uint__BInstancesMapIndex, sptr__BInstance );
return sptr__BInstance;
}
shared_ptr<B> A::CreateBInstance( const string str___CustomColor )
{ unsigned int uint__BInstancesMapIndex = UPTR__BInstancesMap->size();
shared_ptr<B> sptr__BInstance = BFactory::CreateBInstance( uint__BInstancesMapIndex, str___CustomColor );
UPTR__BInstancesMap->insert( uint__BInstancesMapIndex, sptr__BInstance );
return sptr__BInstance;
}
...
文件B.h
#ifndef B_H
#define B_H
using namespace std // Makes these examples easier to read.
class B
{ public:
enum class ENUM_STANDARD_COLORS : unsigned int
{ ... // ~70 standard colors
};
// virtual // BFactory cannot be instantiated; it needs no destructor
~B();
protected:
static unique_ptr<B> CreateBInstance( const unsigned int, const ENUM_STANDARD_COLORS );
static unique_ptr<B> CreateBInstance( const unsigned int, const string ); // Custom color
private:
B( const unsigned int ); // Eliminates default constructor, therefore BFactory cannot
// call B::B(); therefore the compiler does not generate
// BFactory::BFactory(); therefore BFactory (and BFactory.o)
// is empty; it doesn't even need a cpp file.
}
#endif
文件B.cpp
#include "B.h"
...
unique_ptr<B> B::CreateBInstance( const unsigned int uint__BInstancesMapIndex, const ENUM_STANDARD_COLORS enum__StandardColor )
{ unique_ptr<B> uptr__BInstance = unique_ptr<B>( new B( uint__BInstancesMapIndex ) );
uptr__BInstance->SetColor( enum__StandardColor );
return uptr__BInstance;
}
unique_ptr<B> B::CreateBInstance( const unsigned int uint__BInstancesMapIndex, const string str___CustomColor )
{ unique_ptr<B> uptr__BInstance = unique_ptr<B>( new B( uint__BInstancesMapIndex ) );
uptr__BInstance->SetColor( str___CustomColor );
return uptr_BInstance;
}
...
文件BFactory.h
#ifndef BFactory_H
#define BFactory_H
#include "B.h"
class BFactory : private B // Make sure anything inherited from B becomes private.
{ friend class A // Friend declaration moved from class B.
};
#endif
更改摘要:
1) Class A不再是class B的好友
2) Class B 的工厂函数是受保护的,所以 BFactory 将继承它们,并且是静态的,这样我们就不需要 BFactory 的实例来调用它们。
3) Class BFactory 是 B 的空子class,没有构造函数、析构函数或局部成员;它只是继承了 B 的工厂函数,并将 class A 声明为友元。
4) Class A 现在调用BFactory 中的静态函数来获取B 的实例,而不是调用B 中的私有函数。
结果是只有 Class A 可以访问 class B 的静态工厂函数,而 class BFactory 不能用于其他任何事情——据我所知.