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

请教一个跨命名空间 C++拷贝构造函数的问题

  •  1
     
  •   hackpro · 2017-05-22 17:27:24 +08:00 · 2047 次点击
    这是一个创建于 2740 天前的主题,其中的信息可能已经有所发展或是发生改变。

    中午吃饭组里一个同事问的,折腾的一下午还是没搞定,牛皮吹大了,请教下大家如何解决,谢谢各位

    基本需求是两个命名空间存在相同的一个类,TA/TB 以示区别

    怎么将命令空间 A 中类 TA 的对象作为命名空间 B 中类 TB 构造函数的参数传入并访问其中的字段?

    #include "stdafx.h"
    #include <iostream>
    
    using namespace std;
    class B::TB;
    
    namespace A
    {
    	class TA
    	{
    	private:
    		char *m_pstr;
    	public:
    		TA(const char *cstr)
    		{
    			if (cstr == nullptr)
    			{
    				m_pstr = nullptr;
    			}
    			else
    			{
    				int len = strlen(cstr);
    				m_pstr = new (nothrow)char[len+1];
    				memcpy(m_pstr, cstr, len);
    				m_pstr[len] = '\0';
    			}
    		}
    
    		friend class B::TB;
    	};
    }
    
    namespace B
    {
    	class TB
    	{
    	private:
    		char *m_pstr;
    	public:
    		TB(const char *cstr)
    		{
    			if (cstr == nullptr)
    			{
    				m_pstr = nullptr;
    			}
    			else
    			{
    				int len = strlen(cstr);
    				m_pstr = new (nothrow)char[len+1];
    				memcpy(m_pstr, cstr, len);
    				m_pstr[len] = '\0';
    			}
    		}
    
    		//friend class A::TA;
    		TB(const A::TA& ta)
    		{
    			this->m_pstr = ta.m_pstr;
    		}
    		~TB()
    		{
    			if (m_pstr != nullptr)
    			{
    				delete []m_pstr;
    				m_pstr = nullptr;
    			}
    		}
    	};
    }
    
    int main(int argc, char* argv[])
    {
    	A::TA a("This is A");
    	B::TB b = a;
    	return 0;
    }
    
    12 条回复    2017-05-23 14:48:14 +08:00
    Damenly0
        1
    Damenly0  
       2017-05-22 17:46:50 +08:00
    using namespace std;
    namespace B{
    class TB;
    }

    namespace A
    {
    xss
        2
    xss  
       2017-05-22 17:57:15 +08:00
    用泛型不可以么,? 这样还可以解耦.....
    ```
    template <class TA> class TB {
    TB(TA& that){
    this.value = that.value;
    }
    }
    ```
    luoqeng
        4
    luoqeng  
       2017-05-22 18:07:45 +08:00
    TB(const A::TA& ta) {
    // this->m_pstr = ta.m_pstr;

    if (ta.m_pstr != NULL) {
    int len = strlen(ta.m_pstr);
    m_pstr = new (nothrow)char[len+1];
    memcpy(m_pstr, ta.m_pstr, len);
    m_pstr[len] = '\0';
    }
    }

    深拷贝就行了啊
    hackpro
        5
    hackpro  
    OP
       2017-05-22 18:49:26 +08:00
    @Damenly0 #1 感谢大神,问题出在声明特定命名空间中函数

    @xss #2 泛型可以解耦啥意思,可以说具体些吗?

    @sfqtsh # 3 感谢提供,清楚地说明白了为啥命名空间中的函数不能直接前置声明

    @luoqeng #4 这个是实例代码,这样做的目的就是为了避免深层拷贝
    RitchieLee
        6
    RitchieLee  
       2017-05-22 18:49:29 +08:00
    @sfqtsh 亲测大佬的方法可解决楼主的问题
    hackpro
        7
    hackpro  
    OP
       2017-05-22 19:11:16 +08:00
    @Damenly0 #1
    @xss #2
    @sfqtsh #3
    @luoqeng #4

    请教各位,如果想将权限收紧,只将命名空间中某个类的函数作为友元,即 B::TB::TB(),上面这段怎么继续改?
    我尝试了下,没有成功……

    namespace A{class TA;}
    namespace B{
    class TB{
    TB(const A::TA& ta);
    };
    }

    namespace A
    {
    class TA
    {
    friend B::TB::TB(const TA& ta);
    };
    }
    Damenly0
        8
    Damenly0  
       2017-05-22 19:37:53 +08:00
    因为 B::TB::TB()已经涉及到具体 B 的实现,而非声明,考虑到 TB 又依赖于 TA 的实现。如#2 所说,可用 template 解耦
    http://stackoverflow.com/questions/10546391/specify-a-class-member-function-as-a-friend-of-another-class
    wevsty
        9
    wevsty  
       2017-05-22 20:25:43 +08:00
    为什么不用继承?
    xss
        10
    xss  
       2017-05-23 09:51:39 +08:00
    或许我写的 template 误导你了. 那个 class TA 实际上应该是 class T.

    实际上按照你的需求, TB 是对 TA 是有一定要求的.
    一般按照这个尿性发展下去, 你的 TB 一定会对 TA 的要求越来越多. 而一旦 TA 有什么风吹草动, 你就得改一大堆东西.


    直接给例子吧:

    xss@xss [09:47:01] : ~/Code
    $ g++ -c test.cpp -o xxxeee
    xss@xss [09:47:09] : ~/Code
    $ cat test.cpp
    template <class T>
    class TB{
    public:
    TB(T& that){
    this.value = that.value;
    }
    friend void T::foo(void);
    private:
    int value;
    };

    我上面并没有生命一个 TA, 直接用 T 代替, 但是实际上也是可以编译通过的.
    这样的话, 你至少不用考虑 TA 的问题, 因为 T 可以是任何东西.....
    hackpro
        11
    hackpro  
    OP
       2017-05-23 14:29:53 +08:00
    @xss 感谢回复 不过大兄弟你这段代码没考虑 namespace 问题啊
    另外代码编译没有问题 但是没有实质的调用 编译器并不会将这段代码实例化……
    xss
        12
    xss  
       2017-05-23 14:48:14 +08:00
    @hackpro 我只是再跟你说解耦的问题.

    namespace 也不影响应该,
    TB<othernamespace::TA>(objTA)

    这个完全是你在实例化这个模板类的时候需要考虑的问题.
    你只需要对 class TB 有个合理的设计就行了.
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5322 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 29ms · UTC 08:00 · PVG 16:00 · LAX 00:00 · JFK 03:00
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.