Qt 二进制兼容 私有数据保护

定义Human类
human.h文件

#ifndef HUMAN_H
#define HUMAN_H
#include <QObject>
#include <QtGlobal>
#include <QDate>

//
/**
 *【一】二进制兼容 前提条件
 *1.C++空对象占1个字节,而不是0个字节;
 *2.类中的成员函数是不占用类对象的内存空间的;
 *3.非静态成员变量是占用对象的内容空间,同时会进行字节对齐;
 *4.静态成员变量是跟着类走的,所有类对象公用它,和成员函数一样,所以是不占用对象内存空间的;
 *5.如果类中有一个或多个虚函数时,则对象内存空间会增加4个字节(32位系统下)用来存放虚函数表指针(virtual table pointer);
 *【二】会破坏二进制兼容的操作
 *1.添加新的虚函数
 *2.改变类的继承
 *3.改变虚函数声明时的顺序
 *4.添加新的非静态成员变量
 *5.改变非静态成员变量的声明顺序 
 *【三】不会破坏二进制兼容的常见操作有
 *1.添加非虚的成员函数
 *2.添加新的类 添加Qt中的信号槽
 *3.在已存在的枚举类型中添加一个枚举值
 *4.添加新的静态成员变量
 *5.修改成员变量名称(偏移量未改变,但是可能会破坏源码兼容!更严重..)
 *6.添加Q_OBJECT,Q_PROPERTY, Q_ENUMS ,Q_FLAGS宏,添加这些宏都是修改了moc生成的文件,而不是类本身
 */

class HumanPrivate;
class Human:public QObject
{
    Q_OBJECT
public:
    Human(QObject* parent);
    QDate Birthday();
    QDate Deathday();
public slots:
    void setBorn(const QDate&);
    void setDied(const QDate&);
signals:
    void NotifyDied(const QDate&);
    void NotifyBorn(const QDate&);
protected:
    HumanPrivate* const d_ptr;
private:
    Q_DECLARE_PRIVATE(Human);// 相关定义声明明确 d_func() ;注意参数是当前类名,是Human
    Q_PRIVATE_SLOT(d_func(),void setBirthday(const QDate &))// 私有类(HumanPrivate)中的槽函数 映射到Human中
    Q_PRIVATE_SLOT(d_func(),void setBirthday(const QDate &))// 同上
    Q_PRIVATE_SLOT(d_func(),void privateSlotPrintName())// 同上
    Q_DISABLE_COPY(Human);// 删除拷贝构造和赋值构造
    Q_DISABLE_MOVE(Human);// 删除移动构造和移动赋值 (c++11新特性,右值概念、std::move这些东西)
};

class Male:public Human
{
public:
    using Human::Human;
};

class Female:public Human
{
public:
    using Human::Human;
};
#endif // HUMAN_H

human.cpp文件

#include "human.h"
#include <QDebug>
class HumanPrivate
{
public:
    HumanPrivate(Human *parent): q_ptr(parent) {}
    QDate getBirthday() const;
    void setBirthday(const QDate &newBirthday);

    QDate getDeathday() const;
    void setDeathday(const QDate &newDeathday);

private:
    void privateSlotPrintName(){
        qDebug()<<__func__<<"\tbirthday:"<<birthday<<"\tdeathday:"<<deathday;
    }
    QDate birthday;
    QDate deathday;
private:
    Human * q_ptr;
    Q_DECLARE_PUBLIC(Human);// 注意参数是Human
};
QDate HumanPrivate::getBirthday() const
{
    return birthday;
}

void HumanPrivate::setBirthday(const QDate &newBirthday)
{
    Q_Q(Human);// 可以获取到q指针
    birthday = newBirthday;
    emit q->NotifyBorn(birthday);
}

QDate HumanPrivate::getDeathday() const
{
    return deathday;
}

void HumanPrivate::setDeathday(const QDate &newDeathday)
{
    Q_Q(Human);
    deathday = newDeathday;
    emit q->NotifyDied(deathday);
}


Human::Human(QObject* parent):QObject(parent),d_ptr(new HumanPrivate(this))
{
    connect(this,SIGNAL(NotifyBorn(QDate)),this,SLOT(privateSlotPrintName()));
    connect(this,SIGNAL(NotifyDied(QDate)),this,SLOT(privateSlotPrintName()));
}

void Human::setBorn(const QDate &date)
{
    Q_D(Human);// 获取到d指针
    //d_ptr->setBirthday(date);
    d->setBirthday(date);
}

void Human::setDied(const QDate &date)
{
    d_ptr->setDeathday(date);
}

#include "moc_human.cpp"    //注意要加这个include

main.cpp

#include <QApplication>
#include "human.h"

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Human human(nullptr);
    human.setBorn(QDate(1998,2,2));
    human.setDied(QDate::currentDate());
    return a.exec();
}

输出
privateSlotPrintName birthday: QDate(“1998-02-02”) deathday: QDate(Invalid)
privateSlotPrintName birthday: QDate(“1998-02-02”) deathday: QDate(“2024-04-26”)

  • 5
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值