【问题标题】:Method and inner class with the same name (error: ... conflicts with a previous declaration)方法和内部类同名(错误:...与之前的声明冲突)
【发布时间】:2017-08-07 05:59:41
【问题描述】:

我打算拥有一个具有内部类和名称相似的方法的类。 example1.cpp 的代码编译没有问题,即使我有一个内部类和一个同名的方法B。如果我用小写字母将Position 重命名为positionexample2.cpp 将不起作用。在这种情况下,position() 方法和 position 类相互冲突,我收到:

error: ‘ObjType::position<false> ObjType::position() const’ conflicts with a previous declaration
  inline auto position() const->class position<false>{return {*this};}
                                                                     ^
compilation terminated due to -Wfatal-errors.

这两个类有什么区别?为什么后一个报错,前一个报错?

g++ -std=c++11 exampleX.cpp -Wall -Wextra -Wfatal-errors && ./a.out

.

// example1.cpp

#include <iostream>

class A
{
public:
    friend class B;

    class B
    {
    public:
        int x;
        void show() {std::cout<<"x: "<<x<<std::endl;}
        B(): x(6) {}
    };

    B B()
    {
        class B b;
        return b;
    }
};

int main()
{
    A a;
    a.B().show();
    return 0;
}

.

// example2.cpp

#include <iostream>
#include <type_traits>

class Point
{
public:
    double x,y,z;
    void print() const
    {
        std::cout<<"x:"<<x<<", y:"<<y<<", z:"<<z<<std::endl;
    }
};

class ObjType
{
    template<bool> friend class Position;

    Point data;
public:
    template<bool ByRef>
    class Position
    {
        typename std::conditional<ByRef,ObjType&,ObjType const&>::type ref;
    public:
        inline Position(typename std::conditional<ByRef, ObjType&, ObjType const&>::type ref) : ref(ref) {}
        inline Position(const Point &ref): ref(ref){}
        inline auto operator =(Point const& a)->Position&{ref.data.subvec(0,2)=a; return *this;}
        inline auto operator =(Point&& a)->Position&{data=a; return *this;}
        inline void print() const{ref.data.print();}
    };

    inline ObjType(const Point &data): data(data){}
    inline void print() const{data.print();}
    /*error > */ inline auto position() const->class Position<false>{return {*this};}
    inline auto position()->class Position<true>{return {*this};}
};

int main()
{
    ObjType obj({1.1,1.2,1.3});
    std::cout<<"****************"<<std::endl;
    std::cout<<"obj.print() :"<<std::endl;
    obj.print();
    std::cout<<"obj.position.print() :"<<std::endl;
    obj.position().print();
    std::cout<<"****************"<<std::endl;
    return 0;
}

【问题讨论】:

  • 请注意,对于 c++,位置和位置只是 2 个不同的标识符,例如狗和猫。避免使用仅用于大写的标识符。编译器不会混淆,但程序员(包括你)可能会
  • @GianPaolo,我打算创建一个自动代码生成器。而且由于缺乏术语,我什至更喜欢有一个函数和一个类名相似的。但是,我是干净代码的粉丝。
  • 您(或其他人)将不得不使用自动生成的代码;标识符大小写的差异不会轻易被发现。考虑在前面加上下划线 _ 或其他东西
  • @GianPaolo,问题是当用户同时使用position_position

标签: c++ c++11 compiler-errors


【解决方案1】:

这两个类有什么区别?为什么后一个报错,前一个报错?

我们可以进一步将您的示例简化为以下类:

struct S {
    struct C {};
    void C() {}
};

在这种情况下,标准doesn't forbid 引入了一个名称已经在使用中的类。它确实对这种情况开放:

如果在声明同名变量、函数或枚举器的范围内声明类名,则 [...]

它只是规定如何引用它以及隐藏什么。
另一方面,考虑以下类:

struct S {
    template<typename> struct C {};
    void C() {}
};

在这种情况下,标准strictly forbids it(除了少数例外,此处均不适用):

类模板不得与同一范围内的任何其他模板、类、函数、变量、枚举、枚举器、命名空间或类型同名

因此,您不可能使用相同的标识符命名您的类模板和其他函数。
您仍然可以将所有类型打包在一个封闭的范围内,无论如何您都不会定义具有相同名称的函数。举个例子:

struct S {
    struct T {
        template<typename>
        struct C {};
    };

    void C() {}
};

然后访问它们:

S::T::C<void> c;

【讨论】:

  • 太棒了! :) 这个值得被接受的答案。 :)
  • @Arafangion 谢谢。无论如何,你不应该删除你的答案。答案不被接受的事实并不意味着它必须被清除。
  • 你的答案包括了我的所有东西,而且做得更好,我认为保留它没有任何价值! :) 你想让我把它放回去吗?
  • @Arafangion 我认为任何有意义的答案都应该存在,即使它没有被标记为已接受。 ;-)
【解决方案2】:

您的 example1 和 example2 有一个显着不同:example1 不涉及模板类,这里是 example1 的一个版本也失败了:

#include <iostream>

class A
{
    template<bool> friend class B;
public:
    template<bool ByRef>
    class B
    {
    public:
        int x;
        void show() {std::cout<<"x: "<<x<<std::endl;}
        B(): x(6) {}
    };

    B<true> B()
    {
        class B<true> b;
        return b;
    }
};

int main()
{
    A a;
    a.B().show();
    return 0;
}

【讨论】:

  • example2 的解决方案是什么?我可以有一个内部类+模板和一个同名的方法吗?
  • 我不知道,但我倾向于建议您不要这样做。这很混乱,所以不要这样做。 (不要接受这个作为答案,答案应该涉及失败的技术原因)
猜你喜欢
  • 2012-05-09
  • 1970-01-01
  • 1970-01-01
  • 2018-03-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多