V2EX = way to explore
V2EX 是一个关于分享和探索的地方
Sign Up Now
For Existing Member  Sign In
hackpro
V2EX  ›  C

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

  •  1
     
  •   hackpro · May 22, 2017 · 2611 views
    This topic created in 3266 days ago, the information mentioned may be changed or developed.

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

    基本需求是两个命名空间存在相同的一个类,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 replies    2017-05-23 14:48:14 +08:00
    Damenly0
        1
    Damenly0  
       May 22, 2017
    using namespace std;
    namespace B{
    class TB;
    }

    namespace A
    {
    xss
        2
    xss  
       May 22, 2017
    用泛型不可以么,? 这样还可以解耦.....
    ```
    template <class TA> class TB {
    TB(TA& that){
    this.value = that.value;
    }
    }
    ```
    luoqeng
        4
    luoqeng  
       May 22, 2017
    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
       May 22, 2017
    @Damenly0 #1 感谢大神,问题出在声明特定命名空间中函数

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

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

    @luoqeng #4 这个是实例代码,这样做的目的就是为了避免深层拷贝
    RitchieLee
        6
    RitchieLee  
       May 22, 2017
    @sfqtsh 亲测大佬的方法可解决楼主的问题
    hackpro
        7
    hackpro  
    OP
       May 22, 2017
    @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  
       May 22, 2017
    因为 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  
       May 22, 2017
    为什么不用继承?
    xss
        10
    xss  
       May 23, 2017
    或许我写的 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
       May 23, 2017
    @xss 感谢回复 不过大兄弟你这段代码没考虑 namespace 问题啊
    另外代码编译没有问题 但是没有实质的调用 编译器并不会将这段代码实例化……
    xss
        12
    xss  
       May 23, 2017
    @hackpro 我只是再跟你说解耦的问题.

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

    这个完全是你在实例化这个模板类的时候需要考虑的问题.
    你只需要对 class TB 有个合理的设计就行了.
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Solana   ·   2656 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 41ms · UTC 14:27 · PVG 22:27 · LAX 07:27 · JFK 10:27
    ♥ Do have faith in what you're doing.