栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

Qt开发高级进阶:C++中使用dynamic

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Qt开发高级进阶:C++中使用dynamic

通常,在C++中需要用到各种类型转换,典型的如const_cast, dynamic_cast, reinterpret_cast, static_cast。

这时讲两种实现办法: dynamic_cast和直接计算的办法

(1) dynamic_cast

最常用的,dynamic_cast: 动态类型转换,可以在父类与子类之间进行安全的类型转换,运行时类型检查,并且可以知道自己子类的类型。缺点是耗时稍微有点长。
reinterpret_cast: 强制类型转换,可以在不同类型之间进行强制转换,很难保证移植性。速度快。

这里不打算对各个类型转换进行详细解释,相关文档网络上相当多。这 里只重点讲一下dynamic_cast。

dynamic_cast最大的好处是可以用来进行“安全向下转换”。

假设有类A、B和C,如下,

class A {
};

class B : public class A {
};

class C : public class B {
};

A* pc = new C;

当我们将父类指针指向一个new出来的子类B或C对象时,那么可以使用dynamic_cast将该指针类型安全转换为C或B。

我们来运行一下下面的例子,重点是注意最后那个指针p_grand,

#include 
using namespace std;

template
inline bool instanceof(const T* ptr) {
    return dynamic_cast(ptr) != nullptr;
}

class GrandParent {
public:
    GrandParent() {}
    virtual void test() = 0;
};

class Parent : public GrandParent 
{
public:
    virtual ~Parent() {}
    virtual void test() { std::cout << "Parentn"; }
};

class Child : public Parent {
public:
    virtual void test() { std::cout << "Childn"; }
};

class Someclass {
public:
    Someclass(){}
    virtual void test() { std::cout << "Someclassn"; }
};
int main() {

    Parent p;
    Child  c;
    Someclass  sc;

    Parent*    p_parent = &p;
    Child*     p_child = &c;
    Someclass* p_some = ≻
    GrandParent* p_grand = &c;

    if (instanceof(p_parent)) {
        cout << "p_parent is instance of GrandParent" << endl;
    }
    else {
        cout << "p_parent is NOT instance of GrandParent" << endl;
    }
    if (instanceof(p_parent)) {
        cout << "p_parent is instance of Parent" << endl;
    }
    else {
        cout << "p_parent is NOT instance of Parent" << endl;
    }
    if (instanceof(p_parent)) {
        cout << "p_parent is instance of Child" << endl;
    }
    else {
        cout << "p_parent is NOT instance of Child" << endl;
    }
    if (instanceof(p_parent)) {
        cout << "p_parent is instance of Someclass" << endl;
    }
    else {
        cout << "p_parent is NOT instance of Someclass" << endl;
    }

    cout << "----------------------------------------------------" << endl;
    if (instanceof(p_child)) {
        cout << "p_child is instance of GrandParent" << endl;
    }
    else {
        cout << "p_child is NOT instance of GrandParent" << endl;
    }
    if (instanceof(p_child)) {
        cout << "p_child is instance of Parent" << endl;
    }
    else {
        cout << "p_child is NOT instance of Parent" << endl;
    }
    if (instanceof(p_child)) {
        cout << "p_child is instance of Child" << endl;
    }
    else {
        cout << "p_child is NOT instance of Child" << endl;
    }
    if (instanceof(p_child)) {
        cout << "p_child is instance of Someclass" << endl;
    }
    else {
        cout << "p_child is NOT instance of Someclass" << endl;
    }

    cout << "----------------------------------------------------" << endl;   
    if (instanceof(p_some)) {
        cout << "p_some is instance of GrandParent" << endl;
    }
    else {
        cout << "p_some is NOT instance of GrandParent" << endl;
    }
    if (instanceof(p_some)) {
        cout << "p_some is instance of Parent" << endl;
    }
    else {
        cout << "p_some is NOT instance of Parent" << endl;
    }
    if (instanceof(p_some)) {
        cout << "p_some is instance of Child" << endl;
    }
    if (instanceof(p_some)) {
        cout << "p_some is instance of Someclass" << endl;
    }
    else {
        cout << "p_some is NOT instance of Someclass" << endl;
    }

    cout << "----------------------------------------------------" << endl;
    if (instanceof(p_grand)) {
        cout << "p_grand is instance of GrandParent" << endl;
    }
    else {
        cout << "p_grand is NOT instance of GrandParent" << endl;
    }
    if (instanceof(p_grand)) {
        cout << "p_grand is instance of Parent" << endl;
    }
    else {
        cout << "p_grand is NOT instance of Parent" << endl;
    }
    if (instanceof(p_grand)) {
        cout << "p_grand is instance of Child" << endl;
    }
    else {
        cout << "p_grand is NOT instance of Child" << endl;
    }
    if (instanceof(p_grand)) {
        cout << "p_grand is instance of Someclass" << endl;
    }
    else {
        cout << "p_grand is NOT instance of Someclass" << endl;
    }

}

该例子的输出结果如下,

输出结果:

p_parent is instance of GrandParent
p_parent is instance of Parent
p_parent is NOT instance of Child
p_parent is NOT instance of Someclass
----------------------------------------------------
p_child is instance of GrandParent
p_child is instance of Parent
p_child is instance of Child
p_child is NOT instance of Someclass
----------------------------------------------------
p_some is NOT instance of GrandParent
p_some is NOT instance of Parent
p_some is instance of Someclass
----------------------------------------------------
p_grand is instance of GrandParent
p_grand is instance of Parent
p_grand is instance of Child
p_grand is NOT instance of Someclass

(2) 直接计算的办法

这个办法的特点就是没有类型匹配计算,使用时速度非常快。

这里只是提一下,这种只能针对父类为非虚类时,例如对前面p_grand,因为父类GrandParent是纯虚类,所以不适合,但假设其不是纯虚类,就可以进行正确的计算,

template
inline int CalcBaseOffset() {
    const static int s_off = (reinterpret_cast(static_cast(reinterpret_cast(0x10000000))) - reinterpret_cast(0x10000000));
    return s_off;
};
我们用下面的源码测试一下,
class A {
public:
    A() {}
    void test() {
        cout << "A" << " a= " << a << " b= " << b << " c= " << c << endl;
    }
    int a = 1;
    int b = 2;
    double c = 3;
};

class B {
public:
    B() {}
    void test() {
        cout << "B" << endl;
    }
};

class C {
public:
    C() {}
    void test() {
        cout << "C" << endl;
    }
};

class AB : public A, public B {
public:
    AB() {}
    void test() {
        cout << "AB" << endl;
    }
};

class AC : public A, public C {
public:
    AC() {}
    void test() {
        cout << "AC" << endl;
    }
};

int main() {
    int baseOffset1 = CalcBaseOffset();
    int baseOffset2 = CalcBaseOffset();
    assert(baseOffset1 == baseOffset2);

    AB* p1 = new AB;
    AC* p2 = new AC;
    p1->test(); 
    p2->test();

    B* pB = p1; //c++ 编译器会正确处理
    C* pC = p2;
    pB->test(); 
    pC->test();

    long long lv = (long long)pB; 
    A* pA1 = (A*)(lv - baseOffset1);
    assert(pA1 == p1);
    cout << pA1 << " == " << p1 << endl;
    lv = (long long)pC;
    A* pA2 = (A*)(lv - baseOffset2);
    assert(pA2 == p2);
    cout << pA2 << " == " << p2 << endl;

    pA1->test();
    pA2->test();

    return 0;
}
输出结果:
AB
AC
B
C
00B28AF0 == 00B28AF0
00B285A8 == 00B285A8
A a= 1 b= 2 c= 3
A a= 1 b= 2 c= 3

本文结束。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/883988.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号