C++Qt设计模式笔记(一)

这本书虽然叫这个名字,但是好像与设计模式没有什么关系,介绍的大部分是C++基础和Qt基础,不过无所谓了,查漏补缺,把忘记过的一些知识点再记录一下。


函数重载

1.编译器确定应该调用哪一个重载函数的步骤:

(1)如果存在一个完全匹配的函数,则调用此函数。

(2)否则,通过标准的类型提升转换来进行匹配。

(3)否则,通过转换构造函数或者转换运算符来进行匹配。

(4)否则,判断是否可以通过省略号(...)来进行匹配。

(5)否则,编译器报错。

看下例子:

class SignDemo{

public:
    SignDemo(int val):m_val(val){}
    void demo(int n)
    {
        cout<<++m_val<<"\tdemo(int)"<<endl;
    }
    void demo(int n) const
    {
        cout<<m_val<<"\tdemo(int) const"<<endl;
    }

//    void demo(const int &n) //与上面的函数重复
//    {
//        cout<<++m_val<<"\tdemo(const int &)"<<endl;
//    }
    void demo(short n)
    {
        cout<<++m_val<<"\tdemo(short)"<<endl;
    }
    void demo(float n)
    {
        cout<<++m_val<<"\tdemo(float)"<<endl;
    }
    void demo(float n) const
    {
        cout<<m_val<<"\tdemo(float) const"<<endl;
    }
    void demo(double n)
    {
        cout<<++m_val<<"\tdemo(double)"<<endl;
    }

private:
    int m_val;
};

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);


    SignDemo sd(5);
    const SignDemo csd(17);
    sd.demo(2); //6	demo(int) 当没有注释掉上面的那个函数时 ,error
    csd.demo(2);//17	demo(int) const
    int i = 3;
    sd.demo(i);//7	demo(int)
    short s = 5;
    sd.demo(s);//8	demo(short)
    csd.demo(s);//17	demo(int) const 不能调用非const 的short函数 所以提升调用int 的const
    sd.demo(2.3);//9	demo(double)注意为double
    float f(4.5);
    sd.demo(f);//10	demo(float)
    csd.demo(f);//17	demo(float) const
    //csd.demo(4.5);//调用int const 还是 float const 傻傻分不清楚

    return a.exec();
}

引用与函数

一、

class Person{
public:
    void setName(QString name)//修改临时变量的值
    {
        name += "wgy";
        m_strName = name;
    }
    QString getName()
    {
        return m_strName;
    }

    QString& getNameV() //从函数返回临时变量的引用,编译器会发生警告, 有的编译器运行会出错
    {
        QString str = m_strName;
        return str;
    }

private:
    QString m_strName;
};

二、内联函数

inline int max(int a,int b)
{
    return a>b? a:b;
}

int main(int argc, char *argv[])
{
    int temp = max(3,5);
    etc...
            
    //编译器会将max的代码展开如下
    int temp;
    {
        int a = 3;
        int b = 5;
        temp = a>b? a:b;
    }
    etc...
}

如果要重复地调用(例如,在一个大型循环中),则inline函数可极大地提高性能。inline函数的缺点时会使编译代码变得更大, 在运行时会占用更多内存。对于需要调用许多次的小型函数,将其声明成inline对内存的影响使微小的,而潜在的性能提升收益会很大。

inline函数与#define宏类似,但有一个重大差异:对#define宏的替换过程是由预处理器处理的,预处理器本质上就是一个文本编辑器。对inline函数的替换过程是由编译器处理的,它会执行更智能的操作,进行正确的类型检查。

https://www.cnblogs.com/fnlingnzb-learner/p/6423917.html

三、带变长实参的函数。

double mean(int n ...)
{
    va_list ap;//ap指向每一个为命名的实参
    double sum(0);
    int count(n);//实参的个数
    va_start(ap,n);//ap从第一个为命名的实参开始
    for (int i=0;i<count;i++)
    {
        sum += va_arg(ap,double);
    }
    va_end(ap);//返会之前清除栈
    return sum/count;
}

int main(int argc, char *argv[])
{
    cout<<mean(4,11.3,45.1,15.6,12.9)<<endl;
}

Qt数据类型

Qt中很多数据类型(QVariant支持的,例如:QList,QImage,QString,QMap,QHash等)都是隐式共享,写时复制,引用计数等。下面拿QString举个例子:

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    QString s1 = "dsdw";    
    QString s2 = s1;
    //s1.clear();

 qDebug()<<s1<<s2;
    s2 = "dsdada";
    qDebug()<<s1<<s2;

    return a.exec();
}

当s1赋值给s2时,二者的地址是一样的。指向同一块内存,输出一样。(隐式共享)

C++Qt设计模式笔记(一)

当我们clear s1时,s1的地址发生了变化,但是s2还是指向那块内存,这时只是引用计数 -1,如果是浅拷贝,那么s2也会被清空,如果是深拷贝,那么s1赋值s2的时候,就不会地址一样。 

C++Qt设计模式笔记(一)

但是当我们重新给s2赋值时,这时的s2的地址发生了变换(copy on write)

C++Qt设计模式笔记(一)

QObject对象管理

C++Qt设计模式笔记(一)

QObject没有公有的复制构造函数或赋值构造函数。向下到QObject类定义的结尾有一个宏Q_DISABLE_COPY(QObject),它显示的确保QObject不会被复制。

父对象存储子对象们的地址,一般按照添加顺序,但是某些情况下会该变顺序,例如:将一个窗口从后面提升到前面。

每个父对象知道它的子对象的地址,子对象知道它的父对象的地址。

w->setParent(W);w->setParent(Z); w会从W的列表中被删除,同时w的父对象也会改变。这叫重父化

事件循环与观察者模式

https://www.cnblogs.com/suzhou/p/dp16obsvr.html

与观察者模式的实现对应下,恍然大悟。

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    return a.exec();
}
今天先写到这。。。。