为什么c ++类不能为函数和数据成员使用相同的名称?
class demo{
public:
int size();
private:
int size;
};
int main(){
return 0;
}
C:\Users\S>g++ demo.c
demo.c:5:7: error: declaration of 'int demo::size'
demo.c:3:7: error: conflicts with previous declaration 'int demo::size()'
答案 0 :(得分:34)
假设您想要获取成员函数size()
的地址,那么您可以这样写:
auto address = &demo::size;
但它也可能是成员数据size
的地址。暧昧的情况。因此,语言规范不允许这样做。
这并不是说C ++委员会不可能提出解决方案,但我认为这样做没有重大收获。因此,标准只是禁止它,以保持简单。
此外,如果将成员函数size()
声明为:
typedef void fun_type();
struct demo
{
fun_type size; //It looks like a member-data, but it's a member-function
};
void demo::size() //define the member function
{
std::cout << "It is crazy!" << std::endl;
}
int main()
{
demo d;
d.size(); //call the function!
}
输出:
太疯狂了!
参见在线演示:http://ideone.com/ZjwyJ
现在,如果我们可以按照上面的说明实现成员函数,那么即使是肉眼也无法添加另一个相同名称的成员:
struct demo
{
fun_type size;
int size; //error - choose a different name for the member!
};
等等这不完全正确,因为故事尚未完成。我需要在这里添加一些不太明显的东西。您可以使用相同的名称添加多个成员:
typedef void fun_type0();
typedef void fun_type1(int a);
typedef void fun_type2(int a, int b);
struct demo
{
fun_type0 member; //ok
fun_type1 member; //ok
fun_type2 member; //ok
};
这是完全有效的代码,因为每个成员都是不同类型的功能,因此您可以将它们定义为:
void demo::member()
{
std::cout << "member()" << std::endl;
}
void demo::member(int a)
{
std::cout << "member(" << a << ")" << std::endl;
}
void demo::member(int a, int b)
{
std::cout << "member(" << a << ", "<< b << ")" << std::endl;
}
测试代码:
int main()
{
demo d;
d.member();
d.member(10);
d.member(200,300);
}
输出:
member()
member(10)
member(200, 300)
结论......
您可以添加具有相同名称的成员,只要它们是不同类型的功能即可。这是启用由名为成员函数重载(或简单函数重载) 1 的功能启用。
1。不幸的是,该语言没有为成员数据提供类似的功能,比如成员数据重载,语言也没有提供跨成员重载(允许成员数据和成员函数具有相同的名称 - 案例在问题中)。功能
所以这里自然会出现一个问题:它们不会导致歧义问题吗?是的,他们这样做。但值得注意的是,C ++委员会提出了一个解决这个模糊问题的解决方案,因为他们看到了这样做的巨大收获,(在函数重载的情况下)。
但问题中的案例仍然含糊不清,因为委员会没有提出解决方案,因为他们没有看到这样做的任何巨大优势(如前所述)。另外,当我说“C ++委员会提出解决方案”时,我并不是说解决方案已经标准化,我只是意味着他们知道编译器如何解决它,以及解决方案的复杂程度。
答案 1 :(得分:6)
因为如果在某个地方使用size
,那么编译器就不知道该怎么做了。它可以是int-data-member,也可以是函数指针。所以编译器无法分离这两种
答案 2 :(得分:6)
作为一个例子(不是最好的,但它可以用视觉解释):
class Size {
std::size_t size_;
public:
Size(std::size_t s = std::size_t() ) : size_(s){}
std::size_t operator()() const {
return size_;
}
void operator()(std::size_t s) {
size_ = s;
}
};
class Demo {
public:
Size size;
};
int main() {
Demo d;
d.size(10);
std::size_t size = d.size();
return 0;
}
基本上变量也可以调用。所以编译器无法知道你的意图。 当然,这是由语言定义的,它不可能在同一范围内与标识符同名。