条款19: 分清成员函数,非成员函数和友元函数
很前几章一样,先提供一个类的代码
//伪代码
class rational {
public:
rational(int numerator = 0, int denominator = 1);
int numerator() const;
int denominator() const;
const rational operator*(const rational& rhs) const;
private:
...
};
class rational //有理数
{
public:
rational(int numerator = 0, int denominator = 1);
rational& operator=(const rational& rhs);
const rational operator*(const rational& rhs);
void print();
int getX()const;
int getY()const;
private:
int x;
int y;
};
int rational::getX()const
{
return x;
}
int rational::getY()const
{
return y;
}
const rational operator*(const rational &r1, const rational &r2)
{
return rational( r1.getX()*r2.getX(), r1.getY()*r2.getY() );
}
void rational::print()
{
cout<<"x= "<<x
<<"y= "<<y<<endl;
}
rational::rational(int numerator , int denominator ):x(numerator), y(denominator)
{
}
rational& rational::operator =(const rational &rhs)
{
if(this==&rhs)
return *this;
x=rhs.x;
y=rhs.y;
return *this;
}
const rational rational::operator*(const rational& rhs)
{
rational r;
r.x=x*rhs.x;
r.y=y*rhs.y;
return r;
}
int main()
{
rational r1(5,10);
rational r2(50,100);
rational r3;
r3=2*r2;
r3.print();
system("pause");
return 0;
}
进行运算符的操作
rational oneeighth(1,
;
rational onehalf(1, 2);
rational result = onehalf * oneeighth; // 运行良好
result = result * oneeighth; // 运行良好
result = onehalf.operator*(2); // 运行良好----->> result = onehalf * 2;
result = 2.operator*(onehalf); // 出错! ----->> result = 2 * onehalf;
这里有两个知识点,在result = 2.operator*(onehalf);result = 2 * onehalf;即这种中因为2没有这样的函数所以导致调用
出错(或者说对函数列表中非*this指针对对应的对象进行转换)。在此期间,编译器还会尝试调用result = operator*(2,
onehalf); 这样的一个非成员函数(在导入的命名空间内寻找)
result = onehalf.operator*(2); 为什么会通过?
这实际上被隐式转换了
const rational temp(2);
result = onehalf * temp; // 同onehalf.operator*(temp);
为什么有这种转换呢?涉及到explicit关键字,如果这样申明那么就禁止转换而报错了
explicit rational(int numerator = 0, // 此构造函数为
int denominator = 1); // explicit
explicit adj.外在的, 清楚的, 直率的, (租金等)直接付款的
那怎么解决呢?既然onehalf.operator*(2);这样能隐式转换,那么也希望2.operator*(onehalf)也能进行转换。但是因为函数
只对非*this对象进行转换所以如果单单依靠对象来带动函数的话是不太可能了。
effective解决的方法为设个和类名一样的空间,但是不提倡友元函数。
分享到:
相关推荐
友元类、友元函数和友元成员函数是C++中实现类间交互的重要方式,它们帮助我们在设计复杂的数据结构和算法时打破封装的限制,提高代码的灵活性和效率。下面我们将深入探讨这三个概念及其工作原理。 首先,**友元类*...
2. **声明友元类**:一个类可以声明另一个类为友元,使得友元类的所有成员函数都可以访问原类的私有和保护成员。例如: ```cpp class FriendClass; class MyClass { private: int myData; public: friend ...
这意味着这个函数可以像普通友元函数一样访问当前类的私有和受保护成员,同时又具备了类成员函数的身份,可以访问其所属类的所有成员。 下面是一个典型的友元成员函数的使用示例: ```cpp class A { private: int...
成员函数和友元函数是两种不同的方法,可以用来实现运算符重载。 **成员函数重载** 成员函数重载是指将运算符作为类的一个成员函数来实现。这样,运算符的操作数之一通常是当前对象(`this`指针)。例如,在上述...
**友元函数** 是一个非成员函数,但它被声明为某个类的友元,这意味着它可以直接访问该类的私有和受保护成员。友元函数不是类的成员,因此它们不在类的封装之内,但它们被赋予了特权,可以无视访问控制规则。这样做...
封装使得对象的数据成员(尤其是私有成员)和成员函数得以隐藏,从而提高了代码的安全性和可维护性。然而,在某些场景下,我们可能需要让一个外部函数或者另一个类的成员函数访问一个类的私有成员。这时就需要用到...
一、友元介绍我们知道,类的成员函数可以访问同类的其他成员函数,包括公有、私有和保护成员。而类的外部函数只能访问类的公有成员。友元是一种允许非类成员函数访问类的非公有成员的一种机制。可以把一个函数指定为...
2. **访问权限**:友元函数可以访问其友元类的私有和保护成员,但这种访问权限并不传递,即友元函数不能让其他函数或类间接访问友元类的私有和保护成员。 3. **不继承**:子类不会自动继承父类的友元关系。如果需要...
非成员函数可以访问类中的公有成员,但是如果将数据成员都定义为公有的,这又破坏了隐藏的特性。另外,应该看到在某些情况下,特别是在对某些成员函数多次调用时,由于参数传递,类型检查和安全性检查等都需要时间...
运算符重载:友元(friend)函数问题
友元函数不是类的成员,但它可以访问类的私有和保护成员。这样的设计打破了封装的原则,但有时为了实现特定功能,这是必要的。友元函数定义时并不包含作用域解析运算符(::),而是像普通函数一样定义,然后在需要...
其他成员函数和成员变量 ... friend void call(Time &t); // 声明友元函数 private: int hour; int min; int sec; }; // 在类外部定义全局函数call void call(Time &t) { // 因为是Time的友元函数,可以访问...
1. **非成员函数**:友元函数不是类的成员,因此它没有所属的类,但它可以访问类的私有和受保护成员。 2. **权限提升**:友元函数获得了访问权限的提升,可以访问它所友元的类的私有和受保护成员。 3. **非静态关联*...
友元函数是C++中的一种机制,用于打破封装性,让非成员函数可以访问类的私有和保护成员。虽然它能提供一定的便利和效率提升,但使用时需谨慎,因为过度依赖友元函数可能导致代码难以理解和维护,且破坏了面向对象...
通常同一个开发者会出于技术和非技术的原因,控制类的友元和成员函数(否则当你想更新你的类时,还要征得其它部分的拥有者的同意)。 成员函数、非成员函数和友元函数 成员函数和非成员函数最大的区别在于成员函数...
友元函数可以分为三种:普通函数友元函数、友元类和类的成员函数友元函数。 为什么要使用友元函数? -------------------- 在实现类之间的数据共享时,减少系统开销,提高效率。如果类 A 中的函数要访问类 B 中的...
条款19: 分清成员函数,非成员函数和友元函数 条款20: 避免public接口出现数据成员 条款21: 尽可能使用const 条款22: 尽量用“传引用”而不用“传值” 条款23: 必须返回一个对象时不要试图返回一个引用 条款24: 在...
本程序是使用友元成员函数的一个典型例子,简单、实用,对于初学者很有帮助。