如何创建一个类来初始化C++数据类型?

3

标题基本上已经说得很清楚了。我主要想这样做是为了创建一个对象(比如,自定义字符串对象),可以初始化其他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;
}

不幸的是,我收到了一个错误,说操作符=需要成为成员函数。我理解C++标准的目标是防止实现赋值运算符的静态和非成员重载,但是还有其他方法吗?感谢任何帮助/建议!

4个回答

5
这不是通过赋值运算符完成的,而是通过重载类型转换实现的。这将使您的主函数按预期工作:
#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;
}

2
+1,虽然 operator int() 应该是 const,而且如果使用 explicittest(int) 更安全(尽管有时不太方便 - test t = 90)。 - Tony Delroy

3
你想要做的事情需要一个转换运算符
operator int() 
{
    return this->member;
}

对于您尝试编写的类(仅包含整数成员),您不需要重载=运算符。 =运算符是编译器默认为每个类生成的成员函数之一。需要注意的是,它对类成员进行简单的逐位复制(浅复制),由于您只有整数,这应该已经足够了。
如果您有动态分配的指针作为成员函数,则需要重载=运算符,因为在这种情况下,这些指针的浅层副本将导致所有对象都包含一个成员指针,该指针指向相同的动态内存位置,如果其中一个对象完成其生命周期,则其他对象留下悬空指针。
正如@Tony在我们的评论中指出的,浅复制通常是不好的,但并非始终如此。请参见他的评论以获取场景信息。
如果您确实想要重载赋值运算符,请查看复制并交换惯用语以正确地执行它。
您还应该查看三法则

1
"[operator=]会对操作数进行简单的逐位复制(浅复制)...使用operands这个术语有些奇怪...也许应该用成员变量?它会调用具有复制构造函数的成员的构造函数 - 它们可能不会进行逐位复制(例如std::string)。关于指针的浅复制是危险的:通常是正确的,但并非总是如此 - 例如(通常是const)指向静态引用数据的指针可以安全地复制。" - Tony Delroy
1
@Tony:谢谢!我把操作数改成了成员。承认,那不是很详细。我指的是最常见的带有动态内存分配的成员指针情况,因为默认赋值会对新手造成最大的困扰。你的评论应该有助于解释答案中的例外情况,所以谢谢 :) - Alok Save
1
是的 - 我能够理解你的想法,只是担心“新手”可能会认为“任意指针=需要自己的operator=”指南更像是一条规则。不过这是一个很好的指南,正如你所说,对新手有帮助。动态内存是另一个危险信号,虽然不是100%相关:例如,指向的对象可能是由在main()中调用的工厂方法返回的,并且仅在应用程序退出前短时间内删除,而指向它的对象的生命周期在其中“包含”。干杯。 - Tony Delroy
啊,现在这就有意义了。了解运算符重载总是很好的,我还需要再复习一下。谢谢! - AutoBotAM

3

试试这个:

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;
}

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

你不能在 int 中定义非静态成员函数,对吗? - unkulunkulu
@unkulunkulu,是的,因为int是一个内置类型。回答已更新。 - Eric Z

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接