C++ object-oriented programming (two) overload

operator--Keyword

Prefix plus ++i 

Fraction& operator++() //Prefix self-increasing and overloading; (prefix version prefix)
  {    num+=den; //Increase first, then return;    return *this;   }



Suffix plus i++

 const Fraction operator ++(int) //Suffix is ​​self-loaded; (postfix version)
  { Fraction old (*this); //Copy construction (object parameter is object). Return first, then increment; ++(*this); //The pre-version of the overload is called; return old;   }
   
   
   


Generally speaking, unary operators are best to be overloaded as members; for binocular operators, it is best to be overloaded as friend functions. It is more convenient to overload binocular operators as friend functions than to overload as member functions. However, Some binocular operators are better to be overloaded as member functions, for example, the assignment operator. Because, if it is overloaded as a friend function, there will be inconsistencies with the assignment semantics. Examples of overloading of other operators 



static

class is globally effective, that is, a variable shared by each class member

The declaration is in the class, but the definition needs to be defined in the global scope, just like global variables

class CDummy {
public:
static int n;
CDummy () {n++; };
~CDummy () { n--; };

};
int CDummy::n=0;


就像我们会在 class中包含 static数据一样,我们也可以使它包含 static 函数。它们表示相同的含义:static函数是全域函数,但是像一个指定 class的对象成员一样被调用。它们只能够引用 static 数据,永远不能引用 class的非静态, 也不能够使用关键字 this,因为 this实际引用了一个对象指针, 但这些 static函数却不是任何 object的成员,而是 class的直接成员


友元函数friend


对 class的不同成员存在 3个层次的内部保护:public, protected 和 private。在成员为 protected 和 private的情况下,它们不能够被从所在的 class以外的部分引用。然而,这个规则可以通过在一个 class中使用关键字 friend来绕过,这样我们可以允许一个外部函数获得访问 class的 protected 和private 成员的能力。为了实现允许一个外部函数访问 class的 private 和 protected 成员,我们必须在 class内部用关键字 friend来声明该外部函数的原型,以指定允许该函数共享 class的成员。在下面的例子中我们声明了一个friend 函数 duplicate:

//friend functions
#include <iostream.h>
class CRectangle {
int width, height;
public:
void set_values (int, int);
int area (void) {return (width * height);}
friend CRectangle duplicate (CRectangle);
};
void CRectangle::set_values (int a, int b) {
width = a;
height = b;
}
CRectangle duplicate (CRectangle rectparam) {

CRectangle rectres;
rectres.width = rectparam.width*2;
rectres.height = rectparam.height*2;

return (rectres);
}

int main () {
CRectangle rect, rectb;
rect.set_values (2,3);
rectb = duplicate (rect);
cout << rectb.area();
}

函数 duplicate是 CRectangle的 friend,因此在该函数之内,我们可以访问CRectangle 类型的各个 object的成员 width 和 height。注意,在 duplicate()的声明中,及其在后面 main()里被调用的时候,我们并没有把 duplicate 当作 classCRectangle的成员,它不是。friend 函数可以被用来实现两个不同 class之间的操作。广义来说,使用 friend 函数是面向对象编程之外的方法,因此,如果可能,应尽量使用 class的成员函数来完成这些操作。比如在以上的例子中,将函数 duplicate() 集成在 class CRectangle 可以使程序更短。

友元类 (Friend classes)
就像我们可以定义一个 friend 函数,我们也可以定义一个 class是另一个的 friend,以
便允许第二个 class访问第一个 class的 protected 和 private 成员。
//friend class
#include <iostream.h>
class CSquare;

class CRectangle {
int width, height;
public:
int area (void) {return (width * height);}
void convert (CSquare a);
}

Class CSquare {
private:
int side;
public:
void set_side (int a){side=a;}
friend class CRectangle;//CRectangle能访问CSquare类的数据
};
void CRectangle::convert (CSquare a) {
width = a.side;
height = a.side;
}


int main () {
CSquare sqr;
CRectangle rect;
sqr.set_side(4);
rect.convert(sqr);
cout << rect.area();
return 0;
}

在这个例子中,我们声明了 CRectangle 是 CSquare 的 friend,因此CRectangle可以访问 CSquare 的 protected 和 private 成员,可以访CSquare::side。在上面程序的第一个语句里你可能也看到了一些新的东西,就是 class CSquare空原型。这是必需的,因为在 CRectangle 的声明中我们引用了 CSquare (作为 convert()的参数)。CSquare 的定义在 CRectangle的后面,因此如果我们没有在这个 class之前包含一个 CSquare 的声明,它在 CRectangle中就是不可见的。


这里要考虑到,如果没有特别指明,友元关系(friendships)并不是相互的。在我们
的 CSquare 例子中,CRectangle 是一个 friend类,但因为 CRectangle 并没有对
CSquare作相应的声明,因此 CRectangle 可以访问 CSquare 的 protected 和 private
成员,但反过来并不行,除非我们将 CSquare 也定义为 CRectangle的 friend。








什么是从基类中继承的? (What is inherited from the base class?)
理论上说,子类(drived class)继承了基类(base class)的所有成员,除了:
·构造函数 Constructor 和析构函数 destructor
·operator=() 成员
·friends
虽然基类的构造函数和析构函数没有被继承,但是当一个子类的 object被生成或销毁
的时候,其基类的默认构造函数 (即,没有任何参数的构造函数)和析构函数总是被自
动调用的。
如果基类没有默认构造函数,或你希望当子类生成新的 object时,基类的某个重载的
构造函数被调用,你需要在子类的每一个构造函数的定义中指定它:

Guess you like

Origin blog.csdn.net/hgz_gs/article/details/51836326