【问题标题】:How do I create a class that can initialize C++ data types?如何创建一个可以初始化 C++ 数据类型的类?
【发布时间】:2011-10-13 22:43:06
【问题描述】:

标题基本上说明了一切。我主要想这样做,以便我可以创建一个对象(例如,自定义字符串对象),该对象可以初始化其他 API 中其他函数的参数。这是我试图让自定义整数类工作的示例:

#include <iostream>
using namespace std;

class test
{
public:
    int member;
    test(int i) : member(i) {}

    friend int &operator=(int &i, test t);
};

int &operator=(int &i, test t)
{
   return (i = t.member);
}

int main()
{
    int i;
    test t = 90;

    cout << (i = t);
    return 0;
}

很遗憾,我收到一条错误消息,指出 operator= 必须是成员函数。我了解 C++ 标准的目标是防止实现赋值运算符的静态和非成员重载,但是还有其他方法可以做到这一点吗?感谢您的任何帮助/建议!

【问题讨论】:

    标签: c++ overloading operator-keyword friend assignment-operator


    【解决方案1】:

    您正在尝试做的事情需要一个转换运算符

    operator int() 
    {
        return this->member;
    }
    

    对于您尝试编写的类(仅包含整数成员),您不需要重载= 运算符。

    = 运算符是编译器默认为每个类生成的成员函数之一。需要注意的是,它对类成员进行了简单的逐位复制(浅复制),因为您只有整数,所以对您来说应该足够了。

    如果您将动态分配的指针作为成员函数,则需要重载 = 运算符,因为在这种情况下,这些指针的浅拷贝会导致所有对象都包含指向同一动态内存位置的成员指针& 如果其中一个对象完成了它的生命周期,则其他对象会留下一个悬空指针。
    正如@Tony 一样,恰当地指出 cmets 浅拷贝通常不好,但并非总是。请参阅他的 cmets 以了解场景。

    如果您想重载赋值运算符,请查看 Copy and Swap Idiom 以正确方式进行操作。

    您还应该查看 Rule of Three

    【讨论】:

    • “[operator=] 对操作数进行简单的逐位复制(浅复制)”...操作数是一个奇怪的术语...也许是成员变量?它为拥有它们的成员调用复制构造函数——它们可能不会逐位进行浅拷贝(例如std::string)。指针的浅拷贝是危险的:这通常是正确的,但并非总是如此 - 例如(通常是const)指向静态引用数据的指针可以安全地复制。
    • @Tony:谢谢!我将关于操作数的那一点更改为成员。承认,这不是那么冗长。我指的是具有动态内存分配的成员指针的最常见情况,因为这是对重载的默认分配最伤害新手的地方。您的评论应该有助于破译阅读答案的人的例外情况,所以谢谢:)
    • 是的 - 我可以按照你的想法,只是担心“新手”可能会认为“任何指针 = 需要你自己的操作员 =”指南更像是一条规则。不过,这是一个很好的指导方针,正如你所说,它可以帮助新手。动态记忆是另一个危险信号,虽然不是 100% 相关:例如指向的对象可以由在main() 中调用的工厂方法返回,并且仅在应用程序退出前不久删除,而指向它的对象的生命周期被“包含”在其中)。干杯。
    • 啊,现在说得通了。总是很高兴知道运算符重载,我仍然需要对其进行一些审查。谢谢!
    【解决方案2】:

    这不是通过赋值运算符完成的,而是通过重载的类型转换完成的。这将使您的主要功能按预期工作:

    #include <iostream>
    using namespace std;
    
    class test
    {
    public:
        int member;
        test(int i) : member(i) {}
        operator int() const {return member;}
    };
    
    int main()
    {
        int i;
        test t = 90;
    
        cout << (i = t);
        return 0;
    }
    

    【讨论】:

    • +1,虽然operator int() 应该是const,如果explicittest(int) 更安全(尽管有时不太方便-test t = 90)。
    【解决方案3】:

    赋值运算符不能是友元函数。赋值运算符只能声明为非静态成员函数。这是为了确保它接收 L 值作为其第一个操作数。 []、() 和 -> 运算符也是如此。在您的情况下,由于 int 是内置类型,因此您不能使用成员函数。您可以实现 operator int() 将您的用户定义类型转换为 int。

    【讨论】:

    • 您不能在int 中定义非静态成员函数,可以吗?
    • @unkulunkulu,是的,因为 int 是内置类型。答案已更新。
    【解决方案4】:

    试试这个:

    class test
    {
    public:
        int member;
        test(int i) : member(i) {}
    
        operator int() {return this->member;}
    };
    
    int main(void)
    {
        int i;
        test t = 90;
    
        cout << (i = t);
        return 0;
    }
    

    【讨论】:

      猜你喜欢
      • 2013-08-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-02-16
      • 2017-11-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多