V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
linux40
V2EX  ›  C

关于 c++的 using 声明与析构函数调用问题

  •  
  •   linux40 · 2015-07-16 14:12:51 +08:00 · 941 次点击
    这是一个创建于 3426 天前的主题,其中的信息可能已经有所发展或是发生改变。
    http://www.zhihu.com/question/32233786
    是否与继承有关,为什么using声明了一下string就行呢?
    3 条回复    2015-07-17 07:51:19 +08:00
    hitmanx
        1
    hitmanx  
       2015-07-16 17:16:47 +08:00   ❤️ 2
    挺有意思的,我做了几个实验。

    namespace NS_A
    {
    class A
    {
    public:
    A(){std::cout << "A ctor" << std::endl;}
    ~A(){std::cout << "A dtor" << std::endl;}
    };
    }

    namespace NS_B
    {
    void test()
    {
    NS_A::A* a = new NS_A::A;
    a->~A(); // ok
    operator delete(a);
    }
    }

    int main()
    {
    NS_B::test();
    return 0;
    }
    ==============================
    但是如果这儿加上一个typedef,情况就不一样了。

    namespace NS_A
    {
    class A
    {
    public:
    A(){std::cout << "A ctor" << std::endl;}
    ~A(){std::cout << "A dtor" << std::endl;}
    };

    typedef NS_A::A CloneA; // add typedef here
    }


    namespace NS_B
    {
    void test()
    {
    NS_A::CloneA* a = new NS_A::CloneA;
    a->~CloneA(); // oops, we end up with compile error here
    operator delete(a);
    }
    }

    int main()
    {
    NS_B::test();
    return 0;
    }

    ===============================================
    如果加上一句“using NS_A::CloneA;”,编译就又没有问题了。

    同样的,string是一个typedef,原型是模板类basic_string的一个特化。如果这儿改成它的原型,比如改成以下这样,是可以编译的。

    int main()
    {
    std::string *sp = new std::string("hehe");
    sp->~basic_string(); // ok now
    operator delete (sp);
    return 0;
    }
    clapse
        2
    clapse  
       2015-07-16 21:59:23 +08:00
    楼上举的例子:

    a->~CloneA(); // oops, we end up with compile error here

    此处编译器尝试去解释成 A::~CloneA(),没有成功

    使用 using NS_A::CloneA;
    或者 a->NS_A::CloneA::~CloneA();

    此处编译器将~CloneA()替换成了~A(),编译通过

    我这样理解对吗?
    linux40
        3
    linux40  
    OP
       2015-07-17 07:51:19 +08:00 via Android
    @clapse 具体不知道,一直觉得这种东西写编译器实现时会有更深刻的理解,析构函数在编译器眼里就是~加类型名,这里虽然是CloneA,但CloneA是typedef的,实际类型是A,所以析构函数应该是~A,而using的做用只是将名字在当前作用域可见,这样相互作用就成功了吧,个人乱想。。。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2855 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 21ms · UTC 12:32 · PVG 20:32 · LAX 04:32 · JFK 07:32
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.