C++基本语法知识查漏补缺(一)

以下是本人时隔一段时间再次复习c++基本语法的笔记。学过的知识时间久了就容易忘记。隔一段时间进行回顾。

一)复制构造函数
1、复制构造函数的参数是本类对象的引用

类名(const 类名& 引用名);

如:类内Student(const Student& );

类外:Student::Student(const Student& stu)
{
    int len=strlen(stu.name)+1;
    name=new char[len];
    strcpy(name,stu.name);
    age=stu.age;
    cout<<"Student(const Student& )"<<endl;
}

使用const的原因是为了防止被引用的对象被改变。

关于const这个关键字:

const关键字的作用
(1)作用:

1)欲阻止一个变量被改变,可使用const,在定义该const变量时,需先初始化,以后就没有机会改变他了;

2)对指针而言,可以指定指针本身为const,也可以指定指针所指的数据为const,或二者同时指定为const;

3)在一个函数声明中,const可以修饰形参表明他是一个输入参数,在函数内部不可以改变其值;

4)对于类的成员函数,有时候必须指定其为const类型,表明其是一个常函数,不能修改类的成员变量;

5)对于类的成员函数,有时候必须指定其返回值为const类型,以使得其返回值不为“左值”。

const修饰变量
变量的值不能改变
const修饰指针
如果const位于*的左侧,则const就是用来修饰指针所指向的变量,即指针指向为常量
如果const位于*的右侧,const就是修饰指针本身,即指针本身是常量
指针常量:不能通过指针来修改变量的值。
常量指针:一直指向该变量,不能给该指针赋予其他地址
函数中使用const
const修饰函数参数
表示参数不可变
若参数为引用,可以增加效率
const引用传递和函数按值传递的效果是一样的,但按值传递会先建立一个类对象的副本, 然后传递过去,而它直接传递地址,所以这种传递比按值传递更有效
const按值传递时只是外部对象的拷贝,值的改变不会对外部有什么影响,那么是不是没有什么意义:错,重要的目的就是告诉说这个变量不允许被修改,传引用效率会高一点而已。
const 修饰函数返回值
含义和const修饰变量和指针的含义相同
类中使用const
const修饰成员变量
表示成员变量不能被修改,同时只能在初始化列表中赋值
const修饰成员函数
该函数不能改变对象的成员变量
不能调用非const成员函数,因为任何非const成员函数会有修改成员变量的企图
const的成员函数才能被一个const类对象调用。即const类对象只能调用const成员函数
const关键字不能与static关键字同时使用,因为static关键字修饰静态成员函数,静态成员函数不含有this指针,即不能实例化,const成员函数必须具体到某一实例。
const修饰类对象
对象的任何成员都不能被修改
只能调用const成员函数

二)new,是C++提供的用于动态申请存储空间的运算符

new开辟的空间在堆上,而一般声明的变量存放在栈上。new的使用格式,new出来的是一段空间的首地址。所以一般需要用指针来存放这段地址。

注意以下的区别:

int *p = new int(10);//申请了一个初值为10的整型数据

int *arr = new int[10];//申请了能存放10个整型数据元素的数组,其首地址为arr

delete p; delete[] arr;//注意要删除数组时,需要加[],以表示arr为数组。

int example1()
{
  //可以在new后面直接赋值
  int *p = new int(3);
  //也可以单独赋值
  //*p = 3;
 
  //如果不想使用指针,可以定义一个变量,在new之前用“*”表示new出来的内容
  int q = *new int;
  q = 1;
  cout << q << endl;
 
  return *p;
}

三)this关键字

在C++里面,每一个对象都能通过this指针来访问自己的地址。this是所有成员函数的隐藏参数。

在C++中,当成员函数中某个变量与成员变量名字相同,则使用this关键字来表示成员变量。或者,需要返回类变量或者结构体变量的时候,使用this关键字。

四)友元

有时需要定义一些函数,这些函数不是类的一部分,但又需要频繁地访问类的数据成员,这时可以将这些函数定义为该函数的友元函数。除了友元函数外,还有友元类,两者统称为友元。友元的作用是提高了程序的运行效率(即减少了类型检查和安全性检查等都需要时间开销),但它破坏了类的封装性和隐藏性,使得非成员函数可以访问类的私有成员。

1.友元类:

友元类的所有成员函数都是另一个类的友元函数,都可以访问另一个类中的隐藏信息(包括私有成员和保护成员)。当希望一个类可以存取另一个类的私有成员时,可以将该类声明为另一类的友元类。定义友元类的语句格式如下:friend class 类名;friend和class是关键字,类名必须是程序中的一个已定义过的类。

例如,以下语句说明类B是类A的友元类:
class A
{

public:
friend class B;

};类B的所有成员函数都是类A的友元函数,能存取类A的私有成员和保护成员。

   使用友元类时注意:
         (1) 友元关系不能被继承。 
         (2) 友元关系是单向的,不具有交换性。若类B是类A的友元,类A不一定是类B的友元,要看在类中是否有相应的声明。
         (3) 友元关系不具有传递性。若类B是类A的友元,类C是B的友元,类C不一定是类A的友元,同样要看类中是否有相应的申明
4.总结
友元类虽然好用,但是破坏了面向对象的封装特性。所以慎用

五)构造函数的另一种表示方法:

Time(int hour, int minute, int second):_hour(hour) , _minute(minute) , _second(second) {}表示给_hour赋值hour。依次类推

六)浅拷贝与深拷贝

释放内存一般在析构函数中运行。浅拷贝会把指针变量的地址复制,删除时会因出现删除两次而报错, 深拷贝会重新开辟内存空间。

class Test
{
private:
    int* p;
public:
    Test(int x)
    {
        this->p=new int(x);
        cout << "对象被创建" << endl;
    }
    ~Test()
    {
        if (p != NULL)
        {
            delete p;
        }
        cout << "对象被释放" << endl;
    }
    int getX() { return *p; }
    //深拷贝(拷贝构造函数)
    Test(const Test& a)
    {
        this->p = new int(*a.p);
        cout << "对象被创建" << endl;
    }
    //浅拷贝(拷贝构造函数)
    //Test(const Test& a)
    //{
    //  this->p = a.p;
    //  cout << "对象被创建" << endl;
    //}
};

int main()
{
    Test a(10);
    //我们手动的写拷贝构造函数,C++编译器会调用我们手动写的
    Test b = a;
    return 0;
}
七)static的作用

           1):修饰全局变量时,表明一个全局变量只对定义在同一文件中的函数可见。                   

           2):修饰局部变量时,表明该变量的值不会因为函数终止而丢失。              

           3):修饰函数时,表明该函数只在同一文件中调用。

           4):修饰类的数据成员,表明对该类所有对象这个数据成员都只有一个实例。即该实例归 所有对象共有。

           5):用static修饰不访问非静态数据成员的类成员函数。这意味着一个静态成员函数只能访问它的参数、类的静态数据成员和全局变量

八)静态局部变量

静态局部变量在程序执行到该对象的声明处就被首次初始化,以后函数的调用不再进行初始化(局部变量每次被调用总是被初始化)

九)

为什么静态成员函数不能申明为const

答:这是C++的规则,const修饰符用于表示函数不能修改成员变量的值,该函数必须是含有this指针的类成员函数,函数调用方式为thiscall,而类中的static函数本质上是全局函数,调用规约是__cdecl或__stdcall,不能用const来修饰它。<span style="line-height:26px">一个静态成员函数访问的值是其参数、静态数据成员和全局变量,而这些数据都不是对象状态的一部分。而对成员函数中使用关键字const是表明:函数不会修改该函数访问的目标对象的数据成员。既然一个静态成员函数根本不访问非静态数据成员,那么就没必要使用const了

为什么不能在类的内部定义以及初始化static成员变量,而必须要放到类的外部定义

答:

因为静态成员属于整个类,而不属于某个对象,如果在类内初始化,会导致每个对象都包含该静态成员,这是矛盾的。参考两篇博客:

https://blog.csdn.net/jiayi_yao/article/details/50998765        https://blog.csdn.net/sevenjoin/article/details/81772792

为什么要用得静态成员变量和静态成员函数

答:为了实现共享。因为静态成员函数和静态成员变量属于类,不属于类的实体,这样可以被多个对象所共享

静态成员函数与非静态成员函数的区别答:根本区别:静态成员函数不存在this指针,不能访问非静态成员变量。这篇博客总结的还不错静态成员函数与非静态成员函数的区别_独孤九戒的博客-CSDN博客_静态函数和非静态函数的区别
十)运算符重载

一.赋值运算符:函数名:operator + 运算符号

Date&(类名) operator=(const Date& d)
{
    _year = d._year;
    _month = d._month;
    _day = d._day; 
    return *this;//返回需要赋值的对象本身
}

int main()
{
    Date d1;
    Date d2 = d1;
    return 0;
}
注意这里的返回值,因为最后是赋值给一个类,所以返回值也是类。但这样会使用一次拷贝构造,所以改为用引用,返回值从Date,改为Date&

二.关系运算符.从例子中体会吧

bool Boy::operator>(const Boy &boy)

{

if (power() > boy.power())

{ return true; }

else { return false; }

}

bool Boy::operator<(const Boy &boy) {
    if (power() < boy.power()) {
        return true;
    } else {
        return false;
    }
}

bool Boy::operator==(const Boy &boy) {
    if (power() == boy.power()) {
        return true;
    } else {
        return false;
    }

三.算术运算符,从例子中体会吧

Pig Cow::operator+(const Sheep &sheep) {
                    // 牛肉 * 2    +    // 羊肉 * 3
    float ret = this->weigth * 2 + sheep.getWeigth() * 3;
    // 返回前转换为Pig类型
    return Pig(ret);
}

Pig Cow::operator+(const Cow &cow) {
                    // (牛        +        牛)*    2
    float ret = (this->weigth + cow.weigth) * 2;
    // 返回前转换为Pig类型
    return Pig(ret);
}
 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值