竞博jbo电竞官网网址下载中间多少和函数都以类的成员,指澳优(Ausnutria Hyproca卡塔尔(قطر‎个函数属于哪个类或三个

 基础     |      2020-03-18 13:08

第一:private, public, protected 访问标号的访问范围。

private:只能由1.该类中的函数、2.其友元函数访问。

不能被任何其他访问,该类的对象也不能访问。

protected:可以被1.该类中的函数、2.子类的函数、以及3.其友元函数访问。

但不能被该类的对象访问。

public:可以被1.该类中的函数、2.子类的函数、3.其友元函数访问,也可以由4.该类的对象访问。

 

注:友元函数包括3种:设为友元的普通的非成员函数;设为友元的其他类的成员函数;设为友元类中的所有成员函数。

第二:类的继承后方法属性变化。

private 属性不能够被继承。
使用private继承,父类的protected和public属性在子类中变为private;
使用protected继承,父类的protected和public属性在子类中变为protected;
使用public继承,父类中的protected和public属性不发生改变;

 

如下所示:

                         public:            protected:       private:
public继承            public             protected        不可用 
protected继承      protected        protected        不可用 
private继承          private            private           不可用

protected继承和private继承能降低访问权限。

为了进一步理解三种不同的继续方式在其成员的可见性方面的区别,下面从三种不同角度进行讨论。
  对于公有继续方式:
  (1) 基类成员对其对象的可见性:
  公有成员可见,其他不可见。这里保护成员同于私有成员。
  (2) 基类成员对派生类的可见性:
  公有成员和保护成员可见,而私有成员不可见。这里保护成员同于公有成员。
  (3) 基类成员对派生类对象的可见性:
  公有成员可见,其他成员不可见。
  所以,在公有继续时,派生类的对象可以访问基类中的公有成员;派生类的成员函数可以访问基类中的公有成员和保护成员。这里,一定要区分清楚派生类的对象和派生类中的成员函数对基类的访问是不同的。
  对于私有继续方式:
  (1) 基类成员对其对象的可见性:
  公有成员可见,其他成员不可见。
  (2) 基类成员对派生类的可见性:
竞博jbo电竞官网网址下载 ,  公有成员和保护成员是可见的,而私有成员是不可见的。
  (3) 基类成员对派生类对象的可见性:
  所有成员都是不可见的。
  所以,在私有继续时,基类的成员只能由直接派生类访问,而无法再往下继续。
  对于保护继续方式:
  这种继续方式与私有继续方式的情况相同。两者的区别仅在于对派生类的成员而言,对基类成员有不同的可见性。
  上述所说的可见性也就是可访问性。关于可访问性还有另的一种说法。这种规则中,称派生类的对象对基类访问为水平访问,称派生类的派生类对基类的访问为垂直访问。
  一般规则如下:
  公有继续时,水平访问和垂直访问对基类中的公有成员不受限制;
  私有继续时,水平访问和垂直访问对基类中的公有成员也不能访问;
  保护继续时,对于垂直访问同于公有继续,对于水平访问同于私有继续。
  对于基类中的私有成员,只能被基类中的成员函数和友元函数所访问,不能被其他的函数访问。
  基类与派生类的关系
  任何一个类都可以派生出一个新类,派生类也可以再派生出新类,因此,基类和派生类是相对而言的。
  基类与派生类之间的关系可以有如下几种描述:
  1. 派生类是基类的具体化
  类的层次通常反映了客观世界中某种真实的模型。在这种情况下,不难看出:基类是对若干个派生类的抽象,而派生类是基类的具体化。基类抽取了它的派生类的公共特征,而派生类通过增加行为将抽象类变为某种有用的类型。
  2. 派生类是基类定义的延续
  先定义一个抽象基类,该基类中有些操作并未实现。然后定义非抽象的派生类,实现抽象基类中定义的操作。例如,虚函数就属此类情况。这时,派生类是抽象的基类的实现,即可看成是基类定义的延续。这也是派生类的一种常用方法。
  3. 派生类是基类的组合
  在多继续时,一个派生类有多于一个的基类,这时派生类将是所有基类行为的组合。
  派生类将其本身与基类区别开来的方法是添加数据成员和成员函数。因此,继续的机制将使得在创建新类时,只需说明新类与已有类的区别,从而大量原有的程序代码都可以复用,所以有人称类是“可复用的软件构件”。

原文:

1. 类和对象

class Box
{
   public://private 或 protected
      double length;   // 盒子的长度
      double breadth;  // 盒子的宽度
      double height;   // 盒子的高度
      double getVolume(void)  //类的成员函数
      {
         return length * breadth * height;
      }
      Box();//构造函数
      Box(double length);//带参数的构造函数
      ~Box();//析构函数
      Box(const Box &obj);// 拷贝构造函数
      friend void printWidth( Box box ); //友元函数
   private:
      double *ptr;
};
Box::~Box(void)
{
    cout << "Object is being deleted" << endl;
}
Box::Box(const Box &obj)
{
    cout << "调用拷贝构造函数并为指针 ptr 分配内存" << endl;
    ptr = new double;
    *ptr = *obj.ptr; // 拷贝值
}

Box Box1;// 声明 Box1,类型为 Box
Box Box2;// 声明 Box2,类型为 Box

// box 1 详述
Box1.height = 5.0; 
Box1.length = 6.0; 
Box1.breadth = 7.0;

封装(encapsulation):封装就是将抽象得到的数据和行为或功能)相结合,形成一个有机的整体,也就是将数据与操作数据的源代码进行有机的结合,形成“类”,其中数据和函数都是类的成员。封装的目的是增强安全性和简化编程,使用者不必了解具体的实现细节,而只是要通过 外部接口,一特定的访问权限来使用类的成员。通过封装使一部分成员充当类与外部的接口,而将其他的成员隐蔽起来,这样就达到了对成员访问权限的合理控制,使不同类之间的相互影响减少到最低限度,进而增强数据的安全性和简化程序的编写工作。

成员函数

除了可以在 class 内部定义成员函数,也可以在类的外部使用范围解析运算符 :: 定义该函数,如下:

double Box::getVolume(void)
{
    return length * breadth * height;
}

:: 叫作用域区分符,指明一个函数属于哪个类或一个数据属于哪个类。

:: 可以不跟类名,表示全局数据或全局函数(即非成员函数)。

继承:继承是面向对象软件技术当中的一个概念。如果一个类B继承自另一个类A,就把这个B称为A的子类,而把A称为B的父类。继承可以使得子类具有父类的各种属性和方法,而不需要再次编写相同的代码。在令子类继承父类的同时,可以重新定义某些属性,并重写某些方法,即覆盖父类的原有属性和方法,使其获得与父类不同的功能。

C++ 类访问修饰符

public、private、protected,成员和类的默认访问修饰符是 private。保护(protected)成员变量或函数与私有成员十分相似,但有一点不同,保护成员在派生类(即子类)中是可访问的,而 priavte 是不可以的。

多态Polymorphisn):多态性是允许你将父对象设置成为和一个或更多的他的子对象相等的技术,赋值之后,父对象就可以根据当前赋值给它的子对象的特性以不同的方式运作。简单的说:允许将子类类型的指针赋值给父类类型的指针。多态性在C++中都是通过虚函数Virtual Function)实现的。虚函数就是允许被其子类重新定义的成员函数。而子类重新定义父类虚函数的做法,称为“覆盖”或者称为“重写”override)。

类继承时使用修饰符

有public, protected, private三种继承方式,它们相应地改变了基类成员的访问属性。

  • 1.public 继承:基类 public 成员,protected 成员,private 成员的访问属性在派生类中分别变成:public, protected
  • 2.protected 继承:基类 public 成员,protected 成员,private 成员的访问属性在派生类中分别变成:protected, protected,有继承下来但说父类的成员不能被子类对象调用了
  • 3.private 继承:基类 public 成员,protected 成员,private 成员的访问属性在派生类中分别变成:private, private,有继承下来但父类的成员不能被子类对象调用了

但无论哪种继承方式,上面两点都没有改变:

  • 1.private 成员只能被本类成员(类内)和友元访问,不能被派生类访问;
  • 2.protected 成员可以被派生类访问。
class B : public A{

}

接下来以示例进行讲解:

类的构造函数

会在每次创建类的新对象时执行

注意一种带初始化列表的构造函数

C::C( double a, double b, double c): X(a), Y(b), Z(c)
{
  ....
}
//eg:
Box::Box( double len): length(len)
{
    cout << "Object is being created, length = " << len << endl;
}

//相当于
Box::Box( double len)
{
    cout << "Object is being created, length = " << len << endl;
    length = len;
}

继承:

类的析构函数

在每次删除所创建的对象时执行

析构函数的名称与类的名称是完全相同的,只是在前面加了个波浪号(~)作为前缀,它不会返回任何值,也不能带有任何参数。析构函数有助于在跳出程序(比如关闭文件、释放内存等)前释放资源。

class BaseClass{
public:
    int a;
    void test1();
    virtual void printFunc(){
    cout<<"This is BaseClass."<<endl;
    }
protected:
    int b;
    void test2();
private:
    int c;
};
class DerivedClassA : public BaseClass{
public:
    void printFunc(){
    cout<<"This is DerivedClassA."<<endl;
    }
    void testA(){
       cout<<a<<endl
       <<b<<endl
       <<c<<endl;//报错
    }
private:
    int d;
};

C++ 拷贝构造函数

拷贝构造函数是一种特殊的构造函数,它在创建对象时,是使用同一类中之前创建的对象来初始化新创建的对象。如果在类中没有定义拷贝构造函数,编译器会自行定义一个。拷贝构造函数通常用于:

  • 通过使用另一个同类型的对象来初始化新创建的对象。
  • 复制对象把它作为参数传递给函数
  • 复制对象,并从函数返回这个对象。

如果类带有指针变量,并有动态内存分配,则它必须有一个拷贝构造函数。拷贝构造函数的最常见形式如下:

classname (const classname &obj) {
   // 构造函数的主体
}

访问控制和继承权限

C++ 友元函数

类的友元函数是定义在类外部,但有权访问类的所有私有(private)成员和保护(protected)成员。

尽管友元函数的原型有在类的定义中出现过,但是友元函数并不是成员函数

友元可以是一个函数,该函数被称为友元函数;友元也可以是一个类,该类被称为友元类,在这种情况下,整个类及其所有成员都是友元。

#include <iostream>
using namespace std;

class Box
{
   double width;
public:
   friend void printWidth( Box box );
   void setWidth( double wid );
};

// 成员函数定义
void Box::setWidth( double wid )
{
    width = wid;
}

// 请注意:printWidth() 不是任何类的成员函数
void printWidth( Box box )
{
   /* 因为 printWidth() 是 Box 的友元,它可以直接访问该类的任何成员 */
   cout << "Width of box : " << box.width <<endl;
}

// 程序的主函数
int main( )
{
   Box box;
   // 使用成员函数设置宽度
   box.setWidth(10.0);
   // 使用友元函数输出宽度
   printWidth( box );
   return 0;
}

访问控制:

C++ 内联函数inline

C++ 内联函数是通常与类一起使用。引入内联函数的目的是为了解决程序中函数调用的效率问题。如果一个函数是内联的,那么在编译时,编译器会把该函数的代码副本放置在每个调用该函数的地方。内联函数的定义只能是一行(编译器能正确的替换)。

在基类中,public和private标号具有普通含义:用户代码可以访问类的public成员而不能访问private成员,private成员只能由基类的成员和友元访问。派生类对基类的public和private成员的访问权限与程序中任意其他部分一样:它可以访问public成员而不能访问private成员。有时作为基类的类具有一些成员,它希望允许派生类访问但仍禁止其他用户访问这些成员。对于这样的成员应使用受保护的访问标号。protected成员可以被派生类对象访问但不能被该类型的普通用户访问。

C++ 类的静态成员

使用 static 关键字来把类成员定义为静态的,当声明类的成员为静态时,这意味着无论创建多少个类的对象,静态成员都只有一个副本,在创建第一个对象时,所有的静态数据都会被初始化为零。

不能把静态成员的初始化放置在类的定义中,但是可以在类的外部通过使用范围解析运算符:: 来重新声明静态变量从而对它进行初始化。静态成员函数即使在类对象不存在的情况下也能被调用,静态函数只要使用类名加范围解析运算符 :: 就可以访问。

// 初始化类 Box 的静态成员
int Box::objectCount = 0;

静态成员函数与普通成员函数的区别:

  • 静态成员函数没有 this 指针,只能访问静态成员(包括静态成员变量和静态成员函数)。

继承权限:

2. C++ 继承

class derived-class: access-specifier base-class, base-class

公用继承:基类成员保持自己的访问级别,基类的public成员为派生类的 public成员,基类的protected成员为派生类的protected成员。

C++ 重载运算符和重载函数

C++ 允许在同一作用域中的某个函数和运算符指定多个定义,分别称为函数重载和运算符重载

//重载‘+’运算符,可以把 operator+ 当做函数名
Box operator+(const Box&);
Box operator+(const Box&, const Box&);

受保护继承:基类的public和protected成员在派生类中为protected成员。

3. 多态

不同于

私有继承:基类的的所有成员在派生类中为private成员。

java,直接重写父类的同名函数,子类对象调用同名函数时被编译器设置为基类中的版本,这就是所谓的静态多态,或静态链接

函数调用在程序执行前就准备好了。有时候这也被称为早绑定,因为函数在程序编译期间就已经设置好了。

上述例子中,在派生类中使用基类的数据成员a和b都没有问题,但是使用c就会报错。

虚函数

虚函数 是在基类中使用关键字 virtual 声明的函数。在派生类中重新定义基类中定义的虚函数时,会告诉编译器不要静态链接到该函数。这种操作被称为动态链接,或后期绑定

多态:

纯虚函数

可以在基类中声明一个虚函数,以便在派生类中重新定义该函数更好地适用于对象,基类中又不对虚函数给出有意义的实现,这个时候就会用到纯虚函数。

class Shape {

   protected:

      int width, height;

   public:

      Shape( int a=0, int b=0)

      {

         width = a;

         height = b;

      }

      // pure virtual function

      virtual int area() = 0;//= 0 告诉编译器,函数没有主体,上面的虚函数是纯虚函数。

};

C++ 中的函数调用默认不使用动态绑定。要触发动态绑定,满足两个条件:第一,只有指定为虚函数的成员函数才能进行动态绑定,成员函数默认为非虚函数,非虚函数不进行动态绑定;第二,必须通过基类类型的引用或指针进行函数调用。要理解这一要求,需要理解在使用继承层次中某一类型的对象的引用或指针时会发生什么。

C++ 接口(抽象类)

c++没有特定的关键字定义接口(抽象类)

C++ 接口是使用抽象类来实现的,如果类中至少有一个函数被声明为纯虚函数,则这个类就是抽象类。纯虚函数是通过在声明中使用 "= 0" 来指定的。抽象类不能被用于实例化对象,它只能作为接口使用。如果试图实例化一个抽象类的对象,会导致编译错误。

派生类中对于虚函数的重新定义不需要加virtual关键字,只要基类中有就行。

现在再定义一个派生类:

class DerivedClassB : public BaseClass{
public :
    void printFunc(){
    cout<<"This is DerivedClassB."<<endl;
    }
};

测试示例:

void main() {
    BaseClass *b1,*b2,*b3;
    BaseClass bc;
    DerivedClassA dcA;
    DerivedClassB dcB;
    b1 = &bc;
    b2 = &dcA;
    b3 = &dcB;
    b1->printFunc(); //调用基类的方法
    b2->printFunc();  //调用派生类A的方法
    b3->printFunc();  //调用派生类B的方法
}

友元关系与继承:

友元可以访问类的 private和protected数据。友元关系不能继承。基类的友元对派生类的成员没有特殊访问权限。如果基类被授予友元关系,则只有基类具有特殊访问权限,该基类的派生类不能访问授予友元关系的类。

class Base {
friend class Frnd;
protected:
int i;
};
class D1 : public Base {
protected:
int j;
};
class Frnd {
public:
int mem(Base b) { return b.i; }
int mem(D1 d) { return d.i; } // 报错
inherit
};
class D2 : public Frnd {
public:
int mem(Base b) { return b.i; } // 报错
inherit
};

屏蔽与重载

如果派生类重定义了重载成员,则通过派生类型只能访问派生类中重定义的那些成员。

如果派生类想通过自身类型使用的重载版本,则派生类必须要么重定义所有重载版本,要么一个也不重定义。

有时类需要仅仅重定义一个重载集中某些版本的行为,并且想要继承其他版本的含义,在这种情况下,为了重定义需要特化的某个版本而不得不重定义每一个基类版本,可能会令人厌烦。

派生类不用重定义所继承的每一个基类版本,它可以为重载成员提供 using

声明。一个 using 声明只能指定一个名字,不能指定形参表,因此,为基类成员函数名称而作的 using 声明将该函数的所有重载实例加到派生类的作用域。将所有名字加入作用域之后,派生类只需要重定义本类型确实必须定义的那些函数,对其他版本可以使用继承的定义。

class BaseClass{
public:
    void test1(){
        cout<<"BaseTest1"<<endl;
    }
    virtual void printFunc(){
    cout<<"This is BaseClass."<<endl;
    }
private:
    int a;
};
class DerivedClassA : public BaseClass{
public:
    void printFunc(){
    cout<<"This is DerivedClassA."<<endl;
    }
    void test1(int t){
    cout<<"DerivedClassATest1"<<endl;
    }
private:
    int b;
};
void main() {
    BaseClass bc;
    DerivedClassA dcA;
    bc.test1();
    dcA.test1(1);
    dcA.test1();  //报错,被屏蔽了
    dcA.BaseClass::test1();
}

   通过多态,可实现基类调用被屏蔽的虚函数。使用基类的指针来指向派生类的对象。

本文出自 “我的学习笔记” 博客,请务必保留此出处

) : 封装就是将抽象得到的数据和行为或功能)相结合,形成一个有机的整体,也就是将数据与操作数据的源代码进行有机...