关于重载问题
2014-10-29 09:07
155 查看
http://blog.chinaunix.net/uid-26983585-id-3310398.html
在C++中为什么输入输出流不能重载为类成员函数?
假如说operator << ()这是一个成员函数,mealtime是一个类Time的私有成员,那么如我们看到的,如下一个输出语句:cout<<mealtime;将被编译器处理为发送一条消息到cout,cout.operator<<(mealtime);这表示operator <<必须是类ostream的一个成员,而不是类Time的一个成员。然而,即使能将这个新函数添加到标准ostream中,仍然不希望破坏标准的<iostream>库,因此operator <<必然是一个普通函数,这表示如下输出语句:cout<<mealtime将被编译器看作函数调用operator<<(cout,mealtime);这样operator<<()必须具有两个形参,第一个是ostream类,第二个是Timer类。
大部份的标准库实现中,对ostream,istream类体系采用了构造函数保护继承的方式。。。致使即使以继承的方式来扩展流类,也会在对象实例化时遭遇阻碍。。。
另一方面,标准库中的流类,其插入符函数没有声明为虚函数,因此子类不能对其实现进行覆盖,所以也使成员函数重载遭遇到实质的困难。。。
总的来说,C++标准I/O库非常繁杂且难,其实现思想很多都与常规的OOP有所出入。。。在使用的时候要谨慎,并最好遵从惯例。。。
为什么C++赋值运算符不能被继承?
1,每一个类对象实例在创建的时候,如果用户没有定义“赋值运算符重载函数”,那么,编译器会自动生成一个隐含和默认的“赋值运算符重载函数”。所以,B1的实际上的声明应该类似于下面这种情况:
class A1
{
public:
int operator=(int a)
{
return 8;
}
int operator+(int a)
{
return 9;
}
};
class B1 : public A1
{
public:
B1& operator =(const B1& robj); // 注意这一行是编译器添加的
int operator-(int a)
{
return 7;
}
};
2,C++标准规定:如果派生类中声明的成员与基类的成员同名,那么,基类的成员会被覆盖,哪怕基类的成员与派生类的成员的数据类型和参数个数都完全不同。显然,B1中的赋值运算符函数名operator =和基类A1中的operator =同名,所以,A1中的赋值运算符函数int operator=(int a);被B1中的隐含的赋值运算符函数B1& operator =(const B1& robj);所覆盖。 A1中的int operator=(int a);函数无法被B1对象访问。
3,程序中语句v = 2实际上相当于v.operator =(2);,但是A1中的int operator=(int a);已经被覆盖,无法访问。而B1中默认的B1& operator =(const B1& robj);函数又与参数2的整数类型不相符,无法调用。
4,为了确认B1中默认的B1& operator =(const B1& robj);函数的存在性,可以用以下代码验证:
B1 b;
B1 v;
v = b; // OK, 相当于调用v.operator =(b);
5,所以,“赋值运算符重载函数”不是不能被派生类继承,而是被派生类的默认“赋值运算符重载函数”给覆盖了。
这就是C++赋值运算符重载函数不能被派生类继承的真实原因!
关于本帖问题正确性的解释
在C++中为什么输入输出流不能重载为类成员函数?
假如说operator << ()这是一个成员函数,mealtime是一个类Time的私有成员,那么如我们看到的,如下一个输出语句:cout<<mealtime;将被编译器处理为发送一条消息到cout,cout.operator<<(mealtime);这表示operator <<必须是类ostream的一个成员,而不是类Time的一个成员。然而,即使能将这个新函数添加到标准ostream中,仍然不希望破坏标准的<iostream>库,因此operator <<必然是一个普通函数,这表示如下输出语句:cout<<mealtime将被编译器看作函数调用operator<<(cout,mealtime);这样operator<<()必须具有两个形参,第一个是ostream类,第二个是Timer类。
大部份的标准库实现中,对ostream,istream类体系采用了构造函数保护继承的方式。。。致使即使以继承的方式来扩展流类,也会在对象实例化时遭遇阻碍。。。
另一方面,标准库中的流类,其插入符函数没有声明为虚函数,因此子类不能对其实现进行覆盖,所以也使成员函数重载遭遇到实质的困难。。。
总的来说,C++标准I/O库非常繁杂且难,其实现思想很多都与常规的OOP有所出入。。。在使用的时候要谨慎,并最好遵从惯例。。。
为什么C++赋值运算符不能被继承?
1,每一个类对象实例在创建的时候,如果用户没有定义“赋值运算符重载函数”,那么,编译器会自动生成一个隐含和默认的“赋值运算符重载函数”。所以,B1的实际上的声明应该类似于下面这种情况:
class A1
{
public:
int operator=(int a)
{
return 8;
}
int operator+(int a)
{
return 9;
}
};
class B1 : public A1
{
public:
B1& operator =(const B1& robj); // 注意这一行是编译器添加的
int operator-(int a)
{
return 7;
}
};
2,C++标准规定:如果派生类中声明的成员与基类的成员同名,那么,基类的成员会被覆盖,哪怕基类的成员与派生类的成员的数据类型和参数个数都完全不同。显然,B1中的赋值运算符函数名operator =和基类A1中的operator =同名,所以,A1中的赋值运算符函数int operator=(int a);被B1中的隐含的赋值运算符函数B1& operator =(const B1& robj);所覆盖。 A1中的int operator=(int a);函数无法被B1对象访问。
3,程序中语句v = 2实际上相当于v.operator =(2);,但是A1中的int operator=(int a);已经被覆盖,无法访问。而B1中默认的B1& operator =(const B1& robj);函数又与参数2的整数类型不相符,无法调用。
4,为了确认B1中默认的B1& operator =(const B1& robj);函数的存在性,可以用以下代码验证:
B1 b;
B1 v;
v = b; // OK, 相当于调用v.operator =(b);
5,所以,“赋值运算符重载函数”不是不能被派生类继承,而是被派生类的默认“赋值运算符重载函数”给覆盖了。
这就是C++赋值运算符重载函数不能被派生类继承的真实原因!
关于本帖问题正确性的解释
相关文章推荐
- 关于C++模板和重载的小问题
- 转贴:关于C++模板和重载的小问题
- equals与==关于Object覆盖和重载问题
- C++中关于指针运算符->的重载问题
- Java 关于重载的那点问题
- 关于Java中重载的若干问题
- 关于C++模板和重载的小问题
- 关于虚函数重载遇到的怪问题 -- 为什么经常调用了基类的函数
- 关于构造函数的重载 用this语句的调用问题
- 关于重载的问题
- 关于C++模板和重载的小问题
- 关于方法重载问题
- 关于重载new中如何处理alignment的问题
- 关于方法重载和方法覆盖的实际调用问题
- 关于Python中函数重载问题的思考
- 关于系统函数重载和属性的问题
- 一些关于 c#的重载,覆写,虚方法和抽象方法的问题
- 关于powerbuilder的全局函数重载问题
- 1、C++关于拷贝构造函数和赋值运算符重载问题的测试程序。因为调用顺序不清,导致内存泄漏new delete
- 关于重载和重写、多态问题