友谊和继承

好友功能

原则上,一类的private和protected成员不能从它们所声明的同一类外部访问。然而,这条规则并不适用于 “朋友”

朋友们都与声明的函数或类 friend关键字。

如果它被宣布为一个非成员函数可以访问类的private和protected成员 的朋友那类。由包括在类中该外部函数的声明,并与关键字前述它做 friend

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// friend functions
#include <iostream>
using namespace std;

class Rectangle {
    int width, height;
  public:
    Rectangle() {}
    Rectangle (int x, int y) : width(x), height(y) {}
    int area() {return width * height;}
    friend Rectangle duplicate (const Rectangle&);
};

Rectangle duplicate (const Rectangle& param)
{
  Rectangle res;
  res.width = param.width*2;
  res.height = param.height*2;
  return res;
}

int main () {
  Rectangle foo;
  Rectangle bar (2,3);
  foo = duplicate (bar);
  cout << foo.area() << '\n';
  return 0;
}
24


duplicate函数是一个 朋友Rectangle。因此,功能 duplicate是能够访问成员 widthheight类型的不同对象(其是私有的) Rectangle。通知尽管这既不的声明 duplicate,也不在其以后使用 main,功能 duplicate被认为是类的一个成员 Rectangle。这是不是!它只是访问其私有和保护成员而不成员。

友元函数典型的用例是被两个不同的类,访问这两个私人或受保护的成员之间进行的操作。

友元类

给朋友的功能类似,朋友类是一类,其成员可以访问另一个类的私有或保护成员:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
// friend class
#include <iostream>
using namespace std;

class Square;

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

class Square {
  friend class Rectangle;
  private:
    int side;
  public:
    Square (int a) : side(a) {}
};

void Rectangle::convert (Square a) {
  width = a.side;
  height = a.side;
}
  
int main () {
  Rectangle rect;
  Square sqr (4);
  rect.convert(sqr);
  cout << rect.area();
  return 0;
}
16


在这个例子中,类 Rectangle是类的朋友 Square允许 Rectangle的成员函数访问的私有和保护成员 Square。更具体地说, Rectangle访问成员变量 Square::side,它描述了正方形的边。

还有别的东西在这个新的例子:在节目的开始,有类的空声明 Square。这是必要的,因为类 Rectangle的用途 Square(如成员的参数 convert),并 Square使用 Rectangle(声明它的朋友)。

友谊是永远不会对应除非指定:在我们的例子中, Rectangle被认为是一个朋友类 Square,但广场不被视为一个朋友 Rectangle。因此,成员函数 Rectangle可以访问的protected和private成员 Square而不是周围的其他方式。当然, Square也可宣布的朋友 Rectangle,如果需要的话,授予这样的访问。

友谊的另一个特性是它们不可传递:一个朋友的朋友不被视为朋友,除非明确指定。

类之间的继承

在C ++类可以延长,创建新的类其保留的基类的特性。这一过程,被称为继承,涉及 基类派生类:在 派生类继承的成员 基类,在其顶部可以添加自己的成员。

例如,假设一系列的类来描述2种多边形:长方形和三角形。这两个多边形具有某些共同的性质,例如,以计算它们的区域所需的值:它们都可以简单地用一个高度和宽度(或碱)进行说明。

这可以在带班班世界表示 Polygon:从中我们会得到两个其他的 RectangleTriangle

 
Polygon班将包含成员是两种类型的多边形常见。在我们的例子: widthheight。并 RectangleTriangle将它的派生类,与来自其他一种类型的多边形不同的具体特点。

这是从别人派生类继承基类的所有可访问成员。这意味着,如果一个基类包含一个成员 A,我们得出一个类从它叫另一名成员 B,派生类将同时包含成员 A和成员 B

两个类的继承关系在派生类中声明。派生类定义使用的语法如下: 哪里是派生类的名称,是它所基于的类的名称。的访问说明可能由其它访问说明中的任何一个(取代或)。这种访问说明限制了成员最容易级别从基类继承:使用更容易级成员继承这个级别相反,而与同等或更严格的访问级别成员保持严格的级别在派生类中。

class derived_class_name: public base_class_name
{ /*...*/ };

derived_class_name base_class_name public protected private

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
// derived classes
#include <iostream>
using namespace std;

class Polygon {
  protected:
    int width, height;
  public:
    void set_values (int a, int b)
      { width=a; height=b;}
 };

class Rectangle: public Polygon {
  public:
    int area ()
      { return width * height; }
 };

class Triangle: public Polygon {
  public:
    int area ()
      { return width * height / 2; }
  };
  
int main () {
  Rectangle rect;
  Triangle trgl;
  rect.set_values (4,5);
  trgl.set_values (4,5);
  cout << rect.area() << '\n';
  cout << trgl.area() << '\n';
  return 0;
}
20
10


的类的对象 RectangleTriangle每个包含成员从继承 Polygon。它们是: widthheightset_values

protected课堂上使用访问说明符 Polygon类似 private。其唯一的区别发生在事实上具有继承:当一个类继承一个又一个,派生类中的成员可以访问受保护的成员从基类继承,而不是它的私有成员。

通过声明 widthheight作为 protected代替 private,这些成员也可从派生类访问 RectangleTriangle,而不是仅仅从成员 Polygon。如果他们是公众,他们可能只是在任何地方访问。

我们可以根据其功能可以通过以下方式访问它们总结了不同接入类型:

访问publicprotectedprivate
同一类的成员
派生类的成员没有
不是会员没有没有

其中,“不成员”表示从类以外的任何访问,例如从 main,从另一个类或从函数。

在上面的例子中,成员继承由 RectangleTriangle具有相同的访问权限,因为他们在他们的基类有 Polygon

1
2
3
4
5
Polygon::width           // protected access
Rectangle::width         // protected access

Polygon::set_values()    // public access
Rectangle::set_values()  // public access  
 


这是因为继承关系已使用声明 public在每个派生类的关键字:

 
class Rectangle: public Polygon { /* ... */ }
 


public冒号(后关键字 :)表示成员从它后面(在这种情况下,类继承的最方便的水平 Polygon)将具有从派生的类(本例中 Rectangle)。既然 public是最方便的水平,通过指定该关键字的派生类将继承所有,他们在基类有相同级别成员。

随着 protected,基类的所有公共成员继承为 protected派生类。反之,如果指定了最限制访问级别( private),所有的基类成员被继承的 private

例如,如果女儿是来自我们定义为母亲的一个子类:

 
class Daughter: protected Mother;
 


这将设置 protected为成员较少限制的访问级别 Daughter,它由母亲遗传。即,该被所有成员 publicMother会成为 protectedDaughter。当然,这并不是限制 Daughter从宣告它自己的公共成员。这 限制较少的访问级别的成员继承时,才设置 Mother

如果继承没有指定访问级别,编译器假定私人与关键字声明类 class和公众为那些与申报 struct

事实上,在C ++继承大多数用例应该使用公有继承。当需要为基类其他访问级别,它们通常可以更好地表现为成员变量来代替。

什么是从基类继承?

原则上,公派生类继承访问除基类中的每个成员:

  • 它的构造函数和析构函数
  • 其赋值操作符成员(运算符=)
  • 它的朋友
  • 它的私有成员

尽管获得了构造函数和基类的析构函数的不被继承因为如此,它们会自动由派生类的构造函数和析构函数调用。

除另有规定外,派生类的构造函数调用它的基类(即构造函数不接受参数)的默认构造函数。调用基类的构造函数不同的是可能的,使用相同的语法使用初始化列表中初始化成员变量: 例如:

derived_constructor_name (parameters) : base_constructor_name (parameters) {...}



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
// constructors and derived classes
#include <iostream>
using namespace std;

class Mother {
  public:
    Mother ()
      { cout << "Mother: no parameters\n"; }
    Mother (int a)
      { cout << "Mother: int parameter\n"; }
};

class Daughter : public Mother {
  public:
    Daughter (int a)
      { cout << "Daughter: int parameter\n\n"; }
};

class Son : public Mother {
  public:
    Son (int a) : Mother (a)
      { cout << "Son: int parameter\n\n"; }
};

int main () {
  Daughter kelly(0);
  Son bud(0);
  
  return 0;
}
母亲:没有参数
女儿:INT参数

母亲:INT参数
儿子:INT参数


请注意其中的区别 Mother了新时的构造函数被调用 Daughter对象被创建和当它是一个 Son对象。所不同的是由于不同的构造函数声明 DaughterSon

1
2
Daughter (int a)          // nothing specified: call default constructor
Son (int a) : Mother (a)  // constructor specified: call this specific constructor 
 


多重继承

一个类可以简单的通过指定多个基类,以逗号分隔,在一个类的基类的列表(即,冒号后)从多个类继承。例如,如果程序有一个特定的类来打印屏幕上的所谓的 Output,我们希望我们的类 RectangleTriangle以也继承其成员除了那些 Polygon我们可以这样写:

1
2
class Rectangle: public Polygon, public Output;
class Triangle: public Polygon, public Output; 
 


下面是完整的例子: 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
// multiple inheritance
#include <iostream>
using namespace std;

class Polygon {
  protected:
    int width, height;
  public:
    Polygon (int a, int b) : width(a), height(b) {}
};

class Output {
  public:
    static void print (int i);
};

void Output::print (int i) {
  cout << i << '\n';
}

class Rectangle: public Polygon, public Output {
  public:
    Rectangle (int a, int b) : Polygon(a,b) {}
    int area ()
      { return width*height; }
};

class Triangle: public Polygon, public Output {
  public:
    Triangle (int a, int b) : Polygon(a,b) {}
    int area ()
      { return width*height/2; }
};
  
int main () {
  Rectangle rect (4,5);
  Triangle trgl (4,5);
  rect.print (rect.area());
  Triangle::print (trgl.area());
  return 0;
}
20
10  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值