假设我有以下两个类定义(只有bar()
的访问说明符不同,其他一切都相同):
class MyClass {
public:
void foo();
void bar(); // bar() is public
private:
int member;
};
和
class MyClass {
public:
void foo();
private:
void bar(); // bar() is private
int member;
};
编译器是否认为类在编译器生成的代码方面“不同”? (或者换句话说:除了访问权限检查之外,编译器是否会对它进行不同的处理?)
这是同样的问题:以下代码是否会导致未定义行为等问题? (如果它是以不同的单位编制的,有或没有定义X,并在之后链接在一起。)
class MyClass {
public:
void foo();
#ifdef X
private:
#endif
void bar();
private:
int member;
};
我对独立于编译器的答案以及特定于GCC的答案感兴趣(因为这是我的主要目标编译器)。
如果我们想通过在“包”中定义特定的宏来从C ++中的Java世界“模拟”package private
之类的东西,这就变得很有趣。
答案 0 :(得分:4)
违反单定义规则肯定是未定义的行为,这要求同一类类型的所有定义都相同。
请注意,类的内存布局仅在每个访问级别中指定,因此更改访问级别可以非常逼真地导致类的不同内存布局。
答案 1 :(得分:1)
这似乎不是一个好主意:
更改某些功能或数据成员的访问权限 从私人到公共的例子。有些编译器,这个信息 可能是签名的一部分。如果你需要私人功能 受保护甚至是公共的,你必须添加一个调用的新函数 私人的。
但是,我不认为这会导致未定义的行为,而是应该导致链接错误或符号加载错误。
<强>更新强>
在GCC(4.6.1)上进行测试,更改访问权限没有问题。
答案 2 :(得分:0)
不是直接回答 - 只是一个想法:
通过智能使用friend
关键字,您可以获得与libprivate
黑客相同的效果。您可以限制只访问您的部分隐私。您只需要使用friend
两次:
class Example {
private:
typedef int A;
void fooA() {}
static void barA() {}
typedef int B;
void fooB() {}
static void barB() {}
friend class LibAccessToExample;
};
#ifdef libprivate
class LibAccessToExample {
private:
typedef Example::B B;
static void fooB(Example& e) { e.fooB(); }
static void barB() { Example::barB(); }
// and all the classes needed this access at some state
friend class Example1;
friend class Example2;
friend class Example3;
friend class Example4;
};
#endif
通过智能地使用宏,您可以更轻松地编写代码:
#define LIBCLASSES friend class Example1; friend class Example2; ...
#define FRIENDNAME(clazz) LibAccessTo##clazz
#define FWDDEF(clazz, type) typedef clazz::type type
...
#ifdef libprivate
class FRIENDNAME(Example) {
private:
FWDDEF(Example, B);
FWDSTATICFUNC(Example, void, fooB);
FWDFUNC(Example, void, fooB);
LIBCLASSES;
};
#endif