为什么类不能为函数和数据成员具有相同的名称?

时间:2011-10-14 06:21:35

标签: c++ oop

为什么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()'

3 个答案:

答案 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)

在线演示:http://ideone.com/OM97Q


结论......

您可以添加具有相同名称的成员,只要它们是不同类型的功能即可。这是启用由名为成员函数重载(或简单函数重载) 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;
}

基本上变量也可以调用。所以编译器无法知道你的意图。 当然,这是由语言定义的,它不可能在同一范围内与标识符同名。