在嵌套类中调用operator []的模糊调用

时间:2015-02-23 08:52:52

标签: c++ operator-overloading nested-class ambiguity

我正在尝试创建一个具有矢量功能的数据结构来学习一些C ++。我目前正在尝试编译类似于此的代码:

template<typename T>
class TestClass {
public:
    T* data;
    TestClass(const T& t) { 
        data = new T{ t };
    }
    ~TestClass(void) {}
    TestClass(const TestClass&) {}

    T& operator[](int k) { return *data; }
    const T& operator[](int k) const { return *data; }
    class NestedClass {
    public:
        NestedClass(void) {}
        ~NestedClass(void) {}
        T& operator*(void) { return operator[](0); }
    };

    NestedClass newNestedClass(void) {
        return new NestedClass();
    }
};

我对我的嵌套类中的operator*函数的重载函数进行了模糊调用。虽然我认为我遇到了问题(编译器如何知道它的rhs / lhs)我不完全确定如何修复它。我想使用operator[]函数。

我期待这两条打印线打印出完全相同的东西:

TestClass<int> t(1);
auto n = t.newNestedClass();
cout << t[0] << endl;
cout << *n << endl;
return 0;

有什么建议吗?

1 个答案:

答案 0 :(得分:2)

您为operator[]定义的TestClass绝不是&#34;继承&#34;或以某种方式&#34;嵌入&#34;在您的嵌套类中。

您可以将C ++嵌套类视为普通类,它们位于示例代码中的#34;嵌套命名空间&#34;:TestClass::NestedClass中。

如果您希望嵌套类有operator[],则必须从头开始定义(就像您对TestClass所做的那样)。


编辑1:返回类(C ++ Java)

另请注意,C ++ ,例如Java(具有使用new分配类实例的模式,并依赖垃圾收集器自动收集&#34;垃圾&#34;)。
所以,像这样的代码:

   NestedClass newNestedClass(void) {
        return new NestedClass();
    }

甚至不应该编译。

如果您返回了使用NestedClass动态分配的new实例,则应该向其返回指针,例如:

   // Note the "*" for the returned pointer
   NestedClass* newNestedClass() {
        return new NestedClass();
   }

但是,这更像是一种Java模式。

在C ++中,您可能只想返回NestedClass 的实例,而不需要 new动态分配;这应该工作得很好:

   NestedClass newNestedClass() {
        return NestedClass();
   }

编辑2:正确的资源管理

另请注意,您可能希望T* data;成员 private 以获得更好的封装和信息隐藏功能。您正在提供适当的公共访问器(如operator[]重载)来访问您的类的数据:公开访问者成员函数,数据成员。

此外,您使用data 动态在堆上分配new。您必须释放动态堆分配的内存,以避免内存(和资源)泄漏
这样做的好地方是你的析构函数,例如:

class TestClass {
private:
    T* data;

public:
    ...

    ~TestClass() {
        // Release resoruces dynamically allocated
        delete data;
    }
}

另请注意此代码:

data = new T{t};

只需动态分配T的单个实例,将其初始化为值t

相应的清理代码是:

delete data;

但是,如果要动态分配T的数组,则语法为:

data = new T[elementCount];
// ... initialize data to some value...

和相应的清理语法是:

delete[] data; // Note the []!!

另请注意,如果您要手动管理班级中的资源,还应考虑定义复制构造函数复制作业 operator=()(请参阅所谓的Rule of Three);如果你想实现移动语义,你还应该考虑实现移动构造函数移动作业(在这种情况下,那里有相应的#sa; &#34;规则5&#34; )。

但是,如果您依赖已经可用的 RAII资源管理器,例如std::vector,您就不必花费时间,精力和寻找漏洞,管理资源手动 std::vector 管理所有自动,或者您选择的任何容器类(在这种情况下,您只需一个&#34;零的规则&#34; :)即默认的编译器生成的复制构造函数,复制赋值运算符,移动构造函数,移动赋值运算符和析构函数将做紧事。

但是,当然,如果这是一个学习练习,你可能想要自己实现这些特殊的成员函数。