C++Day2

C++Day2

设计一个类求圆的周长

#include <iostream>
using namespace std;

const double PI=3.14;

class Circle
{
	public://公共权限
    
    //求圆周长
    //类中的函数 称为成员函数/成员方法
    //所有的成员函数都必须在类内声明,但可在类外定义
    double calculateZC();
    {
        return 2*PI*m_R;
    }
    
    //半径
    //类中的变量 称为成员变量/成员属性
    int m_R;
};

void test01()
{
    Circle c1;//c1代表一个圆 通过类创建一个对象 实例化对象
    
    //给c1半径赋值
    c1.m_R=10;
    
    //求c1周长
    cout<<"圆的周长为:"<<c1.calculateZC()<<endl;
}
   
  • 类的基本思想
    • 数据抽象
    • 封装
  • class+类名{成员变量 成员函数};
  • 公共权限
  • 设计成员属性
    • 半径 int m_R;
  • 设计成员函数
    • 获取圆周长 int calculatZC(){}
  • 通过类创建对象的过程称为实例化对象

宏缺陷

  • 必须加括号保证运算完整

    • #define MYADD(x,y) x+y
      
      void test01()
      {
          int a=10;
          int b=20;
          int ret=MYADD(a,b)*20;
          cout<<ret<<endl;//输出不为600
      }
      
      //改为
      #define MYADD01(x,y) ((x)+(y))
      void test02()
      {
          int a=10;
          int b=20;
          int ret=MYADD01(a,b)*20;
          cout<<ret<<endl;
      }
      
  • 即使加了括号,有些运算依旧与预期不符

    • #define M(a,b) (((a)<(b))?(a):(b))
      
      void test02()
      {
      	int a=10;
      	int b=20;
      	
      	int ret=M(++a,b);//预期为11 结果为12 (((++a)<(b))?(++a):(b))
          
          cout<<"ret="<<ret<<endl;
      }
      

内联函数

  • 在C++中,预定义宏是由内联函数实现的。内联函数本身也是一个函数,具有普通函数的所有行为。唯一不同之处在于内联函数会在适当的地方像预定义宏一样展开,不需要函数调用的开销(调用前要保存在寄存器,并在返回时恢复;可能需要拷贝实参;程序转向一个新的位置继续执行)

  • 在普通函数(非成员函数)函数前面加上inline使之成为内联函数,但是必须注意必须函数体与声明结合在一起,否则编译器会将它作为普通函数对待

  • //内联函数
    //函数的声明和实现必须同时加关键字inline才算内联函数
    inline void func()
    inline void func()
    {
        
    }
    
    //类内部的内联函数在类内部定义的函数自动成为内联函数,在函数前都隐式加了inline
    
  • 以下情况编译器可能不会将函数进行内联翻译

    • 存在任何形式的循环语句
    • 存在过多的条件判断语句
    • 函数体过大
    • 对函数进行取址操作
  • 对于小的简单的函数编译器可能会将其内联

constexpr函数

  • 函数的返回类型与所有形参类型都为字面值类型
  • 函数体中必须有且只有一条return语句
  • 通常将内联函数与constexpr函数放在头文件中

函数默认参数与占位参数

//默认参数 形参中:类型 变量=默认值
//如果有一个位置有了默认参数,那么从这个位置从左到右都必须有默认值
int func(int a=10,int b=10)
{
    return a+b;
}

void test01()
{
    cout<<func()<<endl;//20
    cout<<func(20)<<endl;//20+10=30
}

//函数的声明和实现只能有一个提供默认参数
//void A1(int a=10,int b=20);
//void A1(int a=10,int b=20){}
//占位参数 只写一个类型进行占位,调用时必须要传入占位值

void func(int a,int)
{
    
}

void test()
{
    func(10,1);
}

命名的强制类型转换

  • 形式:cast-name(expression);
  • type是转换的目标类型
  • expression是要转换的值
  • cast-name
    • static_cast
      • 任何具有明确定义的类型转换,只要不包含底层const,都可以使用static_cast
    • dynamic_cast
    • const_cast
      • 只能改变运算对象的底层const
    • reinterpret_cast
      • 为运算对象的位模式提供较低层次上的重新解释

函数重载

//函数重载条件
//1.在同一个作用域,在不同作用域下可以函数名与形参均相同
//2.函数名称相同
//3.参数个数、类型、顺序不同
//4.返回值不可以作为函数重载条件
//main函数不能重载
void fun()
{
    
}

void fun(int a)
{
    
}
void myFunc(int &a)
{
    cout<<"myFunc(int &a)调用"<<endl;
}

void myFunc(const int &a)
{
    cout<<"myFunc(const int &a)调用"<<endl;
}

void test()
{
    int a=10;
    myFunc(a);//调用第一个,a为可读可写
    myFunc(10);//调用第二个,第一个为int &a=10不合法,const int &a=10合法
}
//当函数重载遇到默认参数,避免二义性出现
void func(int a,int b=10)
{
    
}

void func(int a)
{
    
}

void test()
{
    func(10);//不知道调用哪一个
}

//如果在内层作用域中声明名字,将隐藏外层作用域中声明的同名实体。在不同的作用域中无法重载函数名。在C++中,名字查找发生在类型检查之前

externC浅析

  • 在C++中有函数重载会修饰函数名,会导致链接失败

  • extern "C" void show();//告诉编译器在别的文件寻找show(),用C语言的方式做链接
    
  • //或者在.h文件中
    #ifdef _cplusplus
    	extern "C" {
    #endif
            
            
     #include <stdio.h>
            void show();
            
     #ifdef _cplusplus
        }
    #endif
    
    
    //将{}中内容用C语言的方式做链接
    

类和对象

类的封装

//C++封装理念:将属性与行为作为一个整体
//将属性与行为加以权限控制

struct Person
{
    char name[64];
    int age;
    
    void PersonEat()
    {
        cout<<name<<"在吃饭"<<endl;
    }
};

struct Dog
{
    char name[64];
    int age;
    
    void DogEat()
    {
        cout<<name<<"在狗粮"<<endl;
    }
};
  • class默认权限为私有权限,struct默认权限为公共权限
  • 访问权限
    • public公共权限
      • 成员在类内类外都可以访问
    • private私有权限
      • 成员在类内可以访问,在类外不可以
      • 儿子不可以访问父亲的private权限
    • protected保护权限
      • 成员在类内可以访问,在类外不可以
      • 儿子可以访问父亲的protected权限

将成员变量设置为私有

class Person
{
public:
    //设置姓名
    void setName(string name)
    {
        m_Name=name;
    }
    //获取姓名
   	string getName()
    {
        return m_Name;
    }
    //获取年龄
    int getAge()
    {
        return m_Age;
    }
    //设置年龄
    void setLover(string lover)
    {
        m_Lover=lover;
        
    }
    
private:
    string m_Name;//姓名 可读可写
    int m_Age;//年龄 只读
    string m_Lover;//情人 只写
    
};

void test01()
{
    Person p;
    //p.m_Name="张三";
    //可以将char*隐式类型转换为string
    p.setName("张三");
    cout<<"姓名:"<<p.getName()<<endl;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值