关于C++的那些事儿(二)

本文详细介绍了面向对象编程的基本概念,包括类、结构体、联合体等数据结构的特点和使用方法,并深入探讨了C++中的访问控制、构造函数、运算符重载等关键特性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  1. 以类为基础架构和设计被称为面向对象编程(OOP),它与事件驱动、数据库,以及图形用户界面应用程序的需求良好地结合。
    • Struct

      struct 类的成员默认是公有的。

    • Class
      默认情况下,成员访问是私有的。
    • Union
      创建一个数据类型,其成员默认是公有访问的,但在一个联合中,所有成员共享内存中相同的地址。其结果是,相同的位置在不同时间可被用来存储不同类型的数据。
关键字描述
public公有访问,(struct关键字创建的数据结构的默认值)。从public:后面起,直到下一个访问级别关键字为止的成员都是公有的,因此可由类的用户访问。注:成员是类的命名空间的一部分,只可以通过该类的一个对象,或说明符号名的作用于(class::的方式)来引用。
private私有访问,对除类自身的成员函数外都不可见。一个例外是使用friend关键字。
protected保护访问,不能直接被外部访问。但受保护的成员可以在其子类中访问,无论是直接访问还是间接访问。

2. 每个类写一个默认的构造函数,是一个很好的防御性编程。

类名::类名(){
// 初始化
}
3.初始化列表
#include <cstring>
class Dog{
public:
    cosnt int gender;
    int age;
    char name[21];
    Dog(int m_f,int a,char *nm):gender(m_f),age(a){
        strncpy(name,nm,20);
    }
};
  1. 析构函数不能被const,volatilestatic。但是,它可以被声明为virtual
  2. 运算符重载
//作为友元的运算符函数
friend 类名 operator + (int n,类名 变量);

//赋值运算符
类名& operator = (const 类名& 参数名){
    ………………
    return *this;
}
// 注意区分
Point pt2=pt1;//调用拷贝构造函数
pt1=pt2;//调用运算符=

//下标运算符
类型& operator [] (const int 索引){
}
通过运算符重载可以是数组越界的可能得到解决。

//两个版本的下标运算符
double& operator [] (const int i);
const double& operator [](const int i) const;

//递增运算和递减运算符
类名& operator++ ();//前缀++point
类名 operator++(int);//后缀point++

//传入和传出转换函数
Point(double newx):x(newx),y(0){}
operator double(){……}//double(类实体)
  1. using 基类::基类; C++11允许派生类继承基类的所有构造函数。
  2. 指向派生类的指针不能指向基类的对象。基类的指针可以指向派生类对象可以调用基类地方法,但不能调用子类的方法。
  3. 虚函数和重载
# include <iostream>
using namespace std;
class Mammal (){
public:
    vitural void sound();
};
class Dog::public Mammal(){
publicvoid sound();//重载
}
class Cat:public Mammal(){
public:
    void sound();//重载
}

Mammal *ptr_to_mammal;
//根据不同指向的不同类型,执行相应类型的方法。因为基类有相同的函数定义。

下面是使用虚函数的一些规则和准则
- 在一般情况下,可能被重载的任何函数都应声明为虚函数
- 当重载一个函数时,类型信息必须与被重载函数的类型信息完全匹配
- 构造函数不能是虚函数,但析构函数可以。

纯虚函数
- virtual 函数声明 =0;

一个具有至少一个纯虚函数的类是一个抽象类(abstract class)。这样的类不能被实例化,但可以声明一个指向这个类的指针

函数声明 OverrideOverride关键字表示只有当它重载基类中的一些声明时才允许此声明,否则标记为一个错误的函数,避免命名错误导致系统创建一个新的函数,却没有达到重在的效果。

  1. C++提供了两种联合:命名联合和匿名联合。
union var_data{
    int n;
    double x;
    char *name[20];
};//在所得的类型中,成员共享同一个内存地址,可以是各种类型的,但每次读取的时候只能包含一个类型的值。
//可以实例化


union{
   int n;
    double x;
    char *name[20]; 
};//不可以实例化
  1. 打包的布尔类
#include<iostream>
using namespace std;

//打包布尔类:创建一个动态长度的虚拟布尔数组
//把每个布尔值存储在1位中
class Pack_bool{
private :
    int max_n;//位的数目
    int nbytes;//所需的字节数
    unsigned char* ptr;//指向数据位的指针
public:
    Pack_bool(int max_number);//构造函数、
    void set_bit(int n);
    void clear_bit(int n);
    bool get_bit(int n);
    void set_all_true(){
        for(int i=0;i<nbytes;++i){ptr[i]=0xFF;}
    }
    void set_all_false(){
        for(int i=0;i<nbytes;++i){ptr[i]=0x00;}
    }
};
//构造函数:把max除以8向上取整,获取存储字节数。
Pack_bool::Pack_bool(int n){
    max_n=n;
    nbytes=(max_n+7)/8;//向上取整
    ptr=new unsigned char[nbytes];
}
//设置位成员函数
//查找目标位并使用按位或(OR) 来设置为1
void Pack_bool::set_bit(int n){
    int i=n/8;
    int j=n%8;
    ptr[i]=ptr[i] | (0x01<<j);//设置为1
}
//查找目标位并使用按位或(AND) 来设置为0
void Pack_bool::clear_bit(int n){
    int i=n/8;
    int j=n%8;
    ptr[i]=ptr[i] & ~(0x01<<j);//设置为0
}
bool Pack_bool::get_bit(int n){
    int i=n/8;
    int j=n%8;
    return (ptr[i] & (0x01<<j))!=0;
}

int main(){
    int sizeOfBits=64;
    Pack_bool pb(sizeOfBits);
    pb.set_all_false();
    for(int i=0;i<sizeOfBits;i+=2){pb.set_bit(i);}
    for(int i=0;i<sizeOfBits;++i){cout<<pb.get_bit(i)<<"\t";}

    cout<<endl;
    cin.ignore();
    return 0;
}
  1. 可变参数模板
    声明一个带有可变参数个数的模板的语法如下所示
template<typename... Elements> class tuple;
template<typename Head, typename... Tail>
class tuple<Head, Tail...> : private tuple<Tail...> {
    Head head;
public:
    /* implementation */
};
template<>
class tuple<> {
    /* zero-tuple implementation */
};

在模板参数 Element 左边出现省略号 … ,就是表示 Element 是一个模板参数包(template type parameter pack)。parameter pack(参数包)是新引入 C++ 中的概念,比如在这个例子中,Element 表示是一连串任意的参数打成的一个包。

现在我们知道parameter pack了,怎么在程序中真正具体地去处理打包进来的“任意个数”的参数呢?我原来以为,编译器会提供一些像get_param<1>(Element) 之类的内建的“参数抽取函数”给程序员使用结果不是!!看来我的思路还是太“过程式了”。其实 C++11 用的是 unpack 和类似函数重载似的“模板特化”来抽取参数的。

第1行声明了一个可以对应任意参数的tuple类,第2行到7行声明了这个类的一个部分特化,注意,这就是抽取参数的典型方法了。

其实就是递归调用。

tuple

tuple是个可变参数的类模板:

#include <tuple>
template<typename... _Types>
class tuple;

std::tuple<int, std::string> tu{ 2,"12iop" };

struct Point
{
    int x;
    int y;
};

void main()
{
    std::tuple<int, std::string> t1{ 1,"qwer" };
    constexpr std::tuple<int, void*> t2{ 10,nullptr };
    std::tuple<int, Point> t3{ 1,{20,89} };
    std::tuple<int, char, std::string> t4{ 1,'t',"qwer" };

    std::cout << std::get<0>(t1) << std::endl; // 1

    constexpr int n2 = std::get<0>(t2);
    std::cout << n2 << std::endl; // 10

    auto s = std::get<char>(t4);
    std::cout << s << std::endl; // t
}
  1. C 字符串函数
函数名函数作用
strcat(s1,s2)把字符串s2连接到s1的后面
strchr(s,ch)查找ch字符的位置
strcspn(s1s_reject)获取直到某个字符的跨度函数,返回从0开始的与s_reject的中的任意字符匹配的第一个字符的位置。
strerror(errno)返回系统指定的错误号的文本字符串
strlen(s)此长度是一个直到但不包含终止空字符的字节数。
strpbrk(s1,s2)返回指向s1内第一个与s2中任何字符匹配的字符的指针。
strspn(s1,s_accept)返回不含s_accept中的任意字符串的第一个位置
strstr(s1,s2)返回s2在s1中的第一次出现的指针
#include <iostream>
#include <cstring> 
using namespace std; 
int main(int argc, const char * argv[])
{
    char* token,input_ln[80+1];
    cin.getline(input_ln,80);
    token = strtok(input_ln," ,");
    while(token) //存在标记时
    {
        cout<<token<<endl;//输出此标记
        token=strtok(NULL," ,");//寻找下一标记
    } 
}

这个是线程不安全的
strtok_r(inout," ,",&ptr);//ptr是额外的指针变量
函数名函数作用
memccpy(目标,源,ch,n)直到遇到ch为止,将不超过n的源复制到目标去
memchr(缓冲区,ch,n)搜索ch
memcmp(缓冲区1,缓冲区2,n)比较
memcpy(目标,源,n)
memmove(dest,source,n)这个可以正确处理内存重叠
第13章

C++ I/O

函数名函数说明
istream对象.getline(cstr,n[,delim_ch=’\n’])把一行输入读取到一个C字符串(cstr),方括号表示第三个参数是可选的。默认是换行符,作用是读取到指定的分隔符的字符串
getline(istream对象,str对象[,delim_ch=’\n’])同上,这里是给str对象。
graph TB
ios类-->ostream

ios类-->istream
ostream-->ofstream

istream-->ifstream

流对象:控制符及标志

cout<<hex;十六进制
cout<<dec;十进制
cout<<showbase<<endl;显示前缀 0x(hex)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值