eyePaddles 发布的文章

// widget.h
#pragram once // 该头文件只能出现一次
#include <QWidget>
namespcace Ui { // 命名空间
    class Widget; // ui_widget.h文件里定义的类,外部声明
}
class Widget: public QWidget {
    Q_OBJECT // 宏,使用信号与槽等META层机制时必须添加,一般继承于QObject的子类都要添加这个宏
public:
    explict Widget(QWidget * parent = nullptr); // 若传入parent则图形化对象之间有了父子容器的关系
    ~Widget(); // 析构函数
private:
    Ui::Widget * ui; // Ui::Widget搭配上面声明的命名空间,指向可视化界面,也就是.ui设计好的窗口界面
};
// widget.cpp
#include "widget.h" // 包含自己的目录用引号。
#include "ui_widget.h" // 每次编译,编译器都会自动生成该头文件的代码

Widget::widget(QWidget * parent): QWidget(parent), ui(new Ui::Widget) { // 类成员冒号初始化,先调用父类的构造函数QWidget(parent),再ui = new Ui::Widget。使用ui指针可以对控件进行操作,例如ui->helloLabel->setText("hello");
    ui->setupUi(this); // 实现了组件的各种设置、信号与槽的关联
}

Widget::~widget() {
    delete ui; // 对象树机制,删除了ui,相当于将整个窗口包含其中所有的控件都删了
}

实例:

// 定义类
class Circle {
public:
    int m_r; // 规范:属性要加m_表示成员属性
    double caculateZC() {
        return 2 * PI * m_r;
    }
}; // 区别于JAVA,要有;

// 使用栈区创建和使用对象的方式,作用域为函数内,函数返回前自动执行对象的析构函数
Circle circle;
circle.m_r = 10;
double l = circle.caculateZC();

函数默认参数

C++有这个特性,JAVA没有

int func(int a, int b = 10, int c = 20) {
    return a+b+c;
}

声明和实现只能有一个默认参数

//正确的书写
int func(int, int, int);
int func(int a, int b = 10, int c = 20) {
    return a+b+c;
}

//正确的书写
int func(int a, int b, int c);
int func(int a, int b = 10, int c = 20) {
    return a+b+c;
}

//错误的书写
int func(int a, int b = 10, int c = 20);
int func(int a, int b = 10, int c = 20) {
    return a+b+c;
}

//错误的书写
int func(int a, int b = 1, int c = 2);
int func(int a, int b = 10, int c = 20) {
    return a+b+c;
}

引用作为重载的条件

void func(int &a) { // int &a = 10; // 不合法,引用变量必须赋初值且指向一处内存空间
    cout << "void func(int &a)被调用" << endl;
}

void func(const int &a) { // 只读,所以func(a)没有func(10)适配
    cout << "void func(const int &a)被调用" << endl;
}

int a = 10;
func(a); // void func(int &a)被调用
func(10); // void func(const int &a)被调用

引用本质上是指针常量

&、*的四种修饰情况:

int a = 1;
int *p = &a; // 定义变量时修饰*,定义指针;使用变量时修饰&,取地址
int &b = a; // 定义变量时修饰&为引用,即取别名
cout << *p << endl; // 使用变量时用*为取值,即a的值1

函数的返回值可以是引用类型

int & func() {
    static int a = 1;
    return a;
}

int b = func();
func() = 2;
cout << b << endl; // b=2

常量引用
作用:修饰形参,可以防止误操作;常量引用结合了常量和引用的优势,既保证值不被修改(常量的优势),也节省了空间(引用的优势)——因为引用本质是指针常量,即不能改变指针指向,指针的优势是只要存储一个地址,当需要传递一个很大的结构体时只需传递结构体的地址而不需要将整个结构体都复制一遍。

const int & ref = 10; // 等价于int temp = 10; const int & ref = temp;
int & a = 10; // 但这种操作不允许,引用一定要引一块合法的内存空间
ref = 20; // 报错,常量引用不能修改

void func(const int & val) {
    val = 10; // 报错,常量引用不能修改
}

在堆区开辟内存的几种方式

  1. malloc函数

    #include <malloc.h>
    int * p = (int *)malloc(sizeof(int) * 10);
  2. new关键字创建数、数组,仅C++

    int * func() {
     int * p = new int[10]; // 用指针接收new出来的堆区空间
     int * q = new int(10); // 区别于上行,这行只创建一个int型变量
     delete q; // 释放q指向的堆区数据
     return p;
    }
    void test() {
     int * p = func();
     delete [] p; // 释放p指向的堆区数据,注意释放数组的写法里有中括号
    }