当前位置: 首页 > news >正文

C++使用技巧(二十):再学public、protected及private用法

1、类的封装与继承

类的一个特征就是封装publicprivate作用就是实现这一目的。用户代码(类外)可以访问public成员而不能访问private成员;private成员只能由类成员(类内)和友元访问。

类的另一个特征就是继承protected的作用就是实现这一目的。protected成员可以被派生类对象访问,不能被用户代码(类外)访问。

案例:

#include<iostream>
#include<assert.h>
#include <cstdlib>  //system("pause");
#include <unistd.h>
using namespace std;
class A
{
    public:
        int a;
        A()
        {
            a1 = 1;
            a2 = 2;
            a3 = 3;
            a = 4;
        }
        void fun(int x1,int x2,int x3,int x4)
        {
            cout << a+x1 << endl;    //正确
            cout << a1+x2 << endl;   //正确
            cout << a2+x3 << endl;   //正确,类内访问
            cout << a3+x4 << endl;   //正确,类内访问
        }
    public:
        int a1;
    protected:
        int a2;
    private:
        int a3;
};

int main()
{
    
    A itema;
    itema.fun(-2,3,4,-6);//调用类函数
    itema.a = 10;    //正确
    itema.a1 = 20;    //正确
    // itema.a2 = 30;    //错误,类外不能访问protected成员
    // itema.a3 = 40;    //错误,类外不能访问private成员
    // system("pause"); //windows
    pause();//在linux系统下实现保留控制台的效果
    return 0;
}


运行:

g++ p_p.cc -o test
./test

2
4
6
-3

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

1.public继承:基类public成员,protected成员,private成员的访问属性在派生类中分别变成:public, protected, private

2.protected继承:基类public成员,protected成员,private成员的访问属性在派生类中分别变成:protected, protected, private

3.private继承:基类public成员,protected成员,private成员的访问属性在派生类中分别变成:private, private, private

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

1.private成员只能被本类成员(类内)和友元访问,不能被派生类访问;

2.protected成员可以被派生类访问。

#include <iostream>
#include <assert.h>
using namespace std;

class A
{
public:
    int a;
    A()
    {
        a1 = 1;
        a2 = 2;
        a3 = 3;
        a = 4;
    }
    void fun()
    {
        cout << a << endl;  //正确
        cout << a1 << endl; //正确
        cout << a2 << endl; //正确
        cout << a3 << endl; //正确
    }

public:
    int a1;

protected:
    int a2;

private:
    int a3;
};
class B : public A
{
public:
    int a;
    B(int i)
    {
        A();
        a = i+2022;
    }
    void fun()
    {
        cout << a << endl;  //正确,public成员
        cout << a1 << endl; //正确,基类的public成员,在派生类中仍是public成员。
        cout << a2 << endl; //正确,基类的protected成员,在派生类中仍是protected可以被派生类访问。
        // cout << a3 << endl; //错误,基类的private成员不能被派生类访问。
    }
};
int main()
{
    B b(10);
    cout << b.a << endl;
    cout << b.a1 << endl; //正确
    // cout << b.a2 << endl; //错误,类外不能访问protected成员
    // cout << b.a3 << endl; //错误,类外不能访问private成员
                          //   system("pause");
    return 0;
}

2、demo补充

C++ 类 & 对象:
声明类的对象,就像声明基本类型的变量一样。下面的语句声明了类 Box 的两个对象:

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

对象 Box1 和 Box2 都有它们各自的数据成员。需要注意的是,私有的成员和受保护的成员不能使用直接成员访问运算符 (.) 来直接访问。

#include <iostream>
 
using namespace std;
 
class Box
{
   public:
      double length;   // 长度
      double breadth;  // 宽度
      double height;   // 高度
      // 成员函数声明
      double get(void);
      void set( double len, double bre, double hei );
};
// 成员函数定义   
double Box::get(void)
{
    return length * breadth * height;
}
 
 //指定无返回的函数参数
void Box::set( double len, double bre, double hei)
{
    length = len;
    breadth = bre;
    height = hei;
}
int main( )
{
   Box Box1;        // 声明 Box1,类型为 Box
   Box Box2;        // 声明 Box2,类型为 Box
   Box Box3;        // 声明 Box3,类型为 Box
   double volume = 0.0;     // 用于存储体积
 
   // box 1 详述
   Box1.height = 5.0; 
   Box1.length = 6.0; 
   Box1.breadth = 7.0;
 
   // box 2 详述
   Box2.height = 10.0;
   Box2.length = 12.0;
   Box2.breadth = 13.0;
 
   // box 1 的体积
   volume = Box1.height * Box1.length * Box1.breadth;
   cout << "Box1 的体积:" << volume <<endl;
 
   // box 2 的体积
   volume = Box2.height * Box2.length * Box2.breadth;
   cout << "Box2 的体积:" << volume <<endl;
 
 
   // box 3 详述 设置指定函数参数
   Box3.set(16.0, 8.0, 12.0); //Box3的
   //相当于公式已经写好,这里只需要调用写好的公式,void函数保证参数的对应输入即可,不用类似Box1.height这里的写法了
   volume = Box3.get(); //Box3的
   cout << "Box3 的体积:" << volume <<endl;
   return 0;
}

继承:
当创建一个类时,您不需要重新编写新的数据成员和成员函数,只需指定新建的类继承了一个已有的类的成员即可。这个已有的类称为基类,新建的类称为派生类。
案例:

// 基类
class Animal {
    // eat() 函数
    // sleep() 函数
};


//派生类
class Dog : public Animal {
    // bark() 函数
};

一个类可以派生自多个类,这意味着,它可以从多个基类继承数据和函数。定义一个派生类,我们使用一个类派生列表来指定基类。类派生列表以一个或多个基类命名,形式如下:

class derived-class: access-specifier base-class

其中,访问修饰符 access-specifier 是 public、protected 或 private 其中的一个,base-class 是之前定义过的某个类的名称。如果未使用访问修饰符 access-specifier,则默认为 private。

假设有一个基类 Shape,Rectangle 是它的派生类,如下所示:

#include <iostream>
 
using namespace std;
 
// 基类
class Shape 
{
   public:
      void setWidth(int w)
      {
         width = w;
      }
      void setHeight(int h)
      {
         height = h;
      }
   protected:
      int width;
      int height;
};
 
// 派生类
class Rectangle: public Shape
{
   public:
      int getArea()
      { 
         return (width * height); 
      }
};
 
int main(void)
{
   Rectangle Rect;
 
   Rect.setWidth(5);
   Rect.setHeight(7);
 
   // 输出对象的面积
   cout << "Total area: " << Rect.getArea() << endl;
 
   return 0;
}

继承类型
当一个类派生自基类,该基类可以被继承为 public、protected 或 private 几种类型。继承类型是通过上面讲解的访问修饰符 access-specifier 来指定的。

我们几乎不使用 protected 或 private 继承,通常使用 public 继承。当使用不同类型的继承时,遵循以下几个规则:

公有继承(public):当一个类派生自公有基类时,基类的公有成员也是派生类的公有成员,基类的保护成员也是派生类的保护成员,基类的私有成员不能直接被派生类访问,但是可以通过调用基类的公有和保护成员来访问。
保护继承(protected): 当一个类派生自保护基类时,基类的公有和保护成员将成为派生类的保护成员。
私有继承(private):当一个类派生自私有基类时,基类的公有和保护成员将成为派生类的私有成员。

多继承
多继承即一个子类可以有多个父类,它继承了多个父类的特性。

C++ 类可以从多个类继承成员,语法如下:

class <派生类名>:<继承方式1><基类名1>,<继承方式2><基类名2>,{
<派生类类体>
};

其中,访问修饰符继承方式是 public、protected 或 private 其中的一个,用来修饰每个基类,各个基类之间用逗号分隔,如上所示。现在让我们一起看看下面的实例:

#include <iostream>
 
using namespace std;
 
// 基类 Shape
class Shape 
{
   public:
      void setWidth(int w)
      {
         width = w;
      }
      void setHeight(int h)
      {
         height = h;
      }
   protected:
      int width;
      int height;
};
 
// 基类 PaintCost
class PaintCost 
{
   public:
      int getCost(int area)
      {
         return area * 70;
      }
};
 
// 派生类
class Rectangle: public Shape, public PaintCost
{
   public:
      int getArea()
      { 
         return (width * height); 
      }
};
 
int main(void)
{
   Rectangle Rect;
   int area;
 
   Rect.setWidth(5);
   Rect.setHeight(7);
 
   area = Rect.getArea();
   
   // 输出对象的面积
   cout << "Total area: " << Rect.getArea() << endl;
 
   // 输出总花费
   cout << "Total paint cost: $" << Rect.getCost(area) << endl;
 
   return 0;
}

参考:https://www.runoob.com/cplusplus/cpp-classes-objects.html

其他:

  1. void test(){}

  2. void test(void){}

  3. void test(void *){}

1和2是相同的,表示test函数不接受任何参数,无论在c还是c++中如果函数不接受参数用2的方式书写是一种良好的习惯

3表示test函数接受一个指针类型的参数,无论是什么指针,只要是指针就可以传入

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • C++使用技巧(二十一):makefile编写
  • 网站设计的严重缺陷
  • C语言使用技巧(二十七):回顾strcpy函数用法
  • 桌面端的移动运算(二)
  • C语言使用技巧(二十八):回顾memcpy()函数用法
  • C语言使用技巧(二十九):回顾fopen,fwrite,fread,fseek,fclose,ftell,fputs,gets,rewind,fprintf函数用法
  • 桌面端的移动运算(三)
  • C语言使用技巧(三十):计算程序运行时间以及自带的函数库calcElapsed(startTime, now())
  • 桌面端的移动计算(四)
  • C/C++音频算法: noise suppression算法及技术资料汇总
  • 经济观察报:新浪打造网络新闻的工业化实验
  • AI模型设计:C++实现深度学习神经网络模型及源码分享
  • C语言使用技巧(三十一):回顾strlen函数简单使用
  • 导航界面
  • python使用技巧(二十七):音频WAV和PCM的互相转换
  • [数据结构]链表的实现在PHP中
  • 2019.2.20 c++ 知识梳理
  • 30天自制操作系统-2
  • android百种动画侧滑库、步骤视图、TextView效果、社交、搜房、K线图等源码
  • ES6, React, Redux, Webpack写的一个爬 GitHub 的网页
  • idea + plantuml 画流程图
  • Java IO学习笔记一
  • JavaScript/HTML5图表开发工具JavaScript Charts v3.19.6发布【附下载】
  • JavaScript创建对象的四种方式
  • PyCharm搭建GO开发环境(GO语言学习第1课)
  • spring security oauth2 password授权模式
  • 构造函数(constructor)与原型链(prototype)关系
  • 关于 Cirru Editor 存储格式
  • 聊聊hikari连接池的leakDetectionThreshold
  • 前端面试题总结
  • 少走弯路,给Java 1~5 年程序员的建议
  • 数组大概知多少
  • 算法---两个栈实现一个队列
  • 微信公众号开发小记——5.python微信红包
  • 一道闭包题引发的思考
  • 京东物流联手山西图灵打造智能供应链,让阅读更有趣 ...
  • ​必胜客礼品卡回收多少钱,回收平台哪家好
  • ​软考-高级-信息系统项目管理师教程 第四版【第19章-配置与变更管理-思维导图】​
  • # AI产品经理的自我修养:既懂用户,更懂技术!
  • #### go map 底层结构 ####
  • #100天计划# 2013年9月29日
  • ${factoryList }后面有空格不影响
  • (1)常见O(n^2)排序算法解析
  • (C++)八皇后问题
  • (C++17) optional的使用
  • (js)循环条件满足时终止循环
  • (LLM) 很笨
  • (附源码)springboot学生选课系统 毕业设计 612555
  • (介绍与使用)物联网NodeMCUESP8266(ESP-12F)连接新版onenet mqtt协议实现上传数据(温湿度)和下发指令(控制LED灯)
  • (七)Java对象在Hibernate持久化层的状态
  • (区间dp) (经典例题) 石子合并
  • (十一)图像的罗伯特梯度锐化
  • (新)网络工程师考点串讲与真题详解
  • (一)80c52学习之旅-起始篇
  • (正则)提取页面里的img标签