重载运算符 << 在使用虚函数后无法正常工作。如何解决这个问题?是因为class继承/合成?
Overloaded operator<< not working good after using virtual function. How to solve this ? It's because of class inheritance/ composition?
我的代码有问题,关于我的虚函数和 input/output 运算符,我不知道如何解决。
提前致歉,这篇文章很长。
首先我创建了 2 个 classes(继承)。 Class A 和 B 喜欢这样 :
class A{
protected:
int x;
public:
A()
{
x=0;
}
A(int x1)
{
x=x1;
}
A(const A &o1)
{
x=o1.x;
}
A &operator=(const A &o1)
{
x=o1.x;
}
friend istream &operator>>(istream &input, A &o1)
{
input >> o1.x;
return input;
}
friend ostream &operator<<(ostream &output, const A &o1)
{
output << o1.x;
return output;
}
virtual void cin2()
{
cin >> *this;
}
friend class C;
};
class B: public A{
protected:
float y;
public:
B(): A()
{
y=0.0;
}
B(int x1, float y1): A(x1)
{
y=y1;
}
B(const B &o2): A(o2)
{
y=o2.y;
}
B &operator=(const B &o2)
{
y=o2.y;
A::operator=(o2);
return *this;
}
friend istream &operator>>(istream &input, B &o2)
{
input >> (A&) o2;
input >> o2.y;
return input;
}
friend ostream &operator<<(ostream &output, const B &o2)
{
output << (A) o2;
output << o2.y;
return output;
}
void cin2()
{
cin >> *this;
}
};
经过测试的输出和输入运算符在这 2 个 class 中运行良好。下面使用 虚方法(那里有解释)
接下来,我想要一个 class,里面有一个来自 class A 的 object。我阅读了有关作文的内容,并尝试做类似的事情。这是 class C:
class C{
protected:
A* obj;
double z;
public:
C()
{
obj=new A;
z=0;
}
C(double z1, const A &obj1)
{
obj=new A(obj1);
z=z1;
}
C(const C &o3)
{
obj=o3.obj;
z=o3.z;
}
C &operator=(const C &o3)
{
obj=o3.obj;
z=o3.z;
return *this;
}
friend istream &operator>>(istream &input, C &o3)
{
input >> o3.z;
B obj2;
o3.obj=&obj2;
o3.obj->cin2();
return input;
}
friend ostream &operator<<(ostream &output, const C &o3)
{
output << o3.z << '\n';
operator<<(output, (B&)o3.obj);
output << '\n';
return output;
}
};
问题来了。
正如我上面所说,我写了一个 虚函数 并在这里调用它,因为:
当我读( cin >>) a class C object 时,我也会自动读一个class A object。我想要的是通过 class A 到他的 child、class B 和 cin(读取)两个 classes 参数。 (因为 class B 运算符 >> 也用于 cin class A 参数)。
有效(每次我读取 class C object 时,它还需要我输入 class A 和 B 参数的值)。
没有用的是打印我刚刚阅读的内容 ( cout << )。我 运行 代码,它打印我 class C 参数(double z)但是在那之后,当它应该打印给 class A 和 B 参数的值时,它打印某种地址(我指定 o3.obj 现在是 class (B&) ,我认为它不应该那样做,虽然我不是很确定)
我怎样才能让它正常工作?
这是主要的:
int m;
cin >>m;
C* v=new C[m+1];
for(int i=1; i<=m;++i)
cin >> v[i];
cout << '\n';
for(int i=1;i<=m;++i)
cout << v[i];
return 0;
我的输入:
1 /// numbers of objects
10 /// class C parameter (float z)
11 /// class A parameter (int x)
10.1 /// Class B parameter (float y)
My output:
10 /// value of class C parameter
494590 /// ? some address
现在,您可能认为如果 class C 在 class B 内部有一个 object 会更容易(这样就不需要虚函数,因为如果我们使用 class B 输入(cin >>),它也会自动读取 class A 参数的值。)好吧,它更容易,但不能满足我的要求。另外,我读到了关于向下转换的内容,dynamic_cast,这可能是我如何以一种聪明的方式解决这个问题的方法,但我不明白在哪里以及如何使用 dynamic_cast。
如果你也能用一些例子回答我(以便更好地理解在这里做什么),我将不胜感激。
可能答案很简单,我太笨了,自己找不到
我很高兴找到答案。如果有时间,请帮帮我。
我重新编写了您的代码以演示您需要做什么。我删除了 istream
部分,但应用于 ostream
代码的原则是相同的。因为 operator<<()
和 operator>>()
是 而不是 成员函数,所以您不能直接从它们获得多态行为。您可以做的就是让它们调用具有多态行为的成员函数。
使这项工作起作用的另一部分是一个新的 C
构造函数,它将指向 A
的指针作为参数。这允许我使用指向 A
或 A
.
的任何子对象 class 的指针来初始化 C
对象
您还会注意到我对代码做了很多其他的小改动。我应用了一些更好的做法(默认成员初始化、初始化部分的完整使用等)并删除了不必要的函数。这些 classes 不需要复制构造函数和赋值运算符重载。
#include <iostream>
#include <memory>
class A {
protected:
int x = 0;
virtual void print(std::ostream &sout) const { sout << x << '\n'; }
public:
A() = default;
A(int x1) : x(x1) {}
virtual ~A() = default;
friend std::ostream &operator<<(std::ostream &output, const A &o1) {
o1.print(output);
return output;
}
};
class B : public A {
protected:
float y = 0.0f;
void print(std::ostream &sout) const override {
sout << y << '\n';
A::print(sout);
}
public:
B() : A() {}
B(int x1, float y1) : A(x1), y(y1) {}
friend std::ostream &operator<<(std::ostream &output, const B &o2) {
o2.print(output);
return output;
}
};
class C {
protected:
double z = 0.0;
std::unique_ptr<A> obj{nullptr};
public:
C() = default;
C(double z1, const A &obj1) : z(z1), obj(new A(obj1)) {}
C(double z1, A *ptrA) : z(z1), obj(ptrA) {} // Newly added
C(const C &o3) : z(o3.z), obj(new A(*(o3.obj))) {}
friend std::ostream &operator<<(std::ostream &output, const C &o3) {
output << o3.z << '\n';
output << *(o3.obj);
return output;
}
};
int main() {
C c(3.14, new B(5, 2.3f));
std::cout << c << '\n';
A a(8);
C c2(4.5, a);
std::cout << c2 << '\n';
return 0;
}
输出:
3.14
2.3
5
4.5
8
我的代码有问题,关于我的虚函数和 input/output 运算符,我不知道如何解决。
提前致歉,这篇文章很长。
首先我创建了 2 个 classes(继承)。 Class A 和 B 喜欢这样 :
class A{
protected:
int x;
public:
A()
{
x=0;
}
A(int x1)
{
x=x1;
}
A(const A &o1)
{
x=o1.x;
}
A &operator=(const A &o1)
{
x=o1.x;
}
friend istream &operator>>(istream &input, A &o1)
{
input >> o1.x;
return input;
}
friend ostream &operator<<(ostream &output, const A &o1)
{
output << o1.x;
return output;
}
virtual void cin2()
{
cin >> *this;
}
friend class C;
};
class B: public A{
protected:
float y;
public:
B(): A()
{
y=0.0;
}
B(int x1, float y1): A(x1)
{
y=y1;
}
B(const B &o2): A(o2)
{
y=o2.y;
}
B &operator=(const B &o2)
{
y=o2.y;
A::operator=(o2);
return *this;
}
friend istream &operator>>(istream &input, B &o2)
{
input >> (A&) o2;
input >> o2.y;
return input;
}
friend ostream &operator<<(ostream &output, const B &o2)
{
output << (A) o2;
output << o2.y;
return output;
}
void cin2()
{
cin >> *this;
}
};
经过测试的输出和输入运算符在这 2 个 class 中运行良好。下面使用 虚方法(那里有解释)
接下来,我想要一个 class,里面有一个来自 class A 的 object。我阅读了有关作文的内容,并尝试做类似的事情。这是 class C:
class C{
protected:
A* obj;
double z;
public:
C()
{
obj=new A;
z=0;
}
C(double z1, const A &obj1)
{
obj=new A(obj1);
z=z1;
}
C(const C &o3)
{
obj=o3.obj;
z=o3.z;
}
C &operator=(const C &o3)
{
obj=o3.obj;
z=o3.z;
return *this;
}
friend istream &operator>>(istream &input, C &o3)
{
input >> o3.z;
B obj2;
o3.obj=&obj2;
o3.obj->cin2();
return input;
}
friend ostream &operator<<(ostream &output, const C &o3)
{
output << o3.z << '\n';
operator<<(output, (B&)o3.obj);
output << '\n';
return output;
}
};
问题来了。 正如我上面所说,我写了一个 虚函数 并在这里调用它,因为:
当我读( cin >>) a class C object 时,我也会自动读一个class A object。我想要的是通过 class A 到他的 child、class B 和 cin(读取)两个 classes 参数。 (因为 class B 运算符 >> 也用于 cin class A 参数)。
有效(每次我读取 class C object 时,它还需要我输入 class A 和 B 参数的值)。 没有用的是打印我刚刚阅读的内容 ( cout << )。我 运行 代码,它打印我 class C 参数(double z)但是在那之后,当它应该打印给 class A 和 B 参数的值时,它打印某种地址(我指定 o3.obj 现在是 class (B&) ,我认为它不应该那样做,虽然我不是很确定) 我怎样才能让它正常工作?
这是主要的:
int m;
cin >>m;
C* v=new C[m+1];
for(int i=1; i<=m;++i)
cin >> v[i];
cout << '\n';
for(int i=1;i<=m;++i)
cout << v[i];
return 0;
我的输入:
1 /// numbers of objects
10 /// class C parameter (float z)
11 /// class A parameter (int x)
10.1 /// Class B parameter (float y)
My output:
10 /// value of class C parameter
494590 /// ? some address
现在,您可能认为如果 class C 在 class B 内部有一个 object 会更容易(这样就不需要虚函数,因为如果我们使用 class B 输入(cin >>),它也会自动读取 class A 参数的值。)好吧,它更容易,但不能满足我的要求。另外,我读到了关于向下转换的内容,dynamic_cast,这可能是我如何以一种聪明的方式解决这个问题的方法,但我不明白在哪里以及如何使用 dynamic_cast。
如果你也能用一些例子回答我(以便更好地理解在这里做什么),我将不胜感激。 可能答案很简单,我太笨了,自己找不到
我很高兴找到答案。如果有时间,请帮帮我。
我重新编写了您的代码以演示您需要做什么。我删除了 istream
部分,但应用于 ostream
代码的原则是相同的。因为 operator<<()
和 operator>>()
是 而不是 成员函数,所以您不能直接从它们获得多态行为。您可以做的就是让它们调用具有多态行为的成员函数。
使这项工作起作用的另一部分是一个新的 C
构造函数,它将指向 A
的指针作为参数。这允许我使用指向 A
或 A
.
C
对象
您还会注意到我对代码做了很多其他的小改动。我应用了一些更好的做法(默认成员初始化、初始化部分的完整使用等)并删除了不必要的函数。这些 classes 不需要复制构造函数和赋值运算符重载。
#include <iostream>
#include <memory>
class A {
protected:
int x = 0;
virtual void print(std::ostream &sout) const { sout << x << '\n'; }
public:
A() = default;
A(int x1) : x(x1) {}
virtual ~A() = default;
friend std::ostream &operator<<(std::ostream &output, const A &o1) {
o1.print(output);
return output;
}
};
class B : public A {
protected:
float y = 0.0f;
void print(std::ostream &sout) const override {
sout << y << '\n';
A::print(sout);
}
public:
B() : A() {}
B(int x1, float y1) : A(x1), y(y1) {}
friend std::ostream &operator<<(std::ostream &output, const B &o2) {
o2.print(output);
return output;
}
};
class C {
protected:
double z = 0.0;
std::unique_ptr<A> obj{nullptr};
public:
C() = default;
C(double z1, const A &obj1) : z(z1), obj(new A(obj1)) {}
C(double z1, A *ptrA) : z(z1), obj(ptrA) {} // Newly added
C(const C &o3) : z(o3.z), obj(new A(*(o3.obj))) {}
friend std::ostream &operator<<(std::ostream &output, const C &o3) {
output << o3.z << '\n';
output << *(o3.obj);
return output;
}
};
int main() {
C c(3.14, new B(5, 2.3f));
std::cout << c << '\n';
A a(8);
C c2(4.5, a);
std::cout << c2 << '\n';
return 0;
}
输出:
3.14
2.3
5
4.5
8