【问题标题】:C++ Nested classes driving me crazyC++ 嵌套类让我发疯
【发布时间】:2008-10-25 21:45:16
【问题描述】:

我正在尝试编译这段非常简单的代码

class myList
{
public:
    std::vector<std::string> vec;
    class Items
    {
    public:
        void Add(std::string str)
        {
            myList::vec.push_back(str);
        };
    }items;
};

int main()
{
    myList newList;
    newList.items.Add("A");
}

在不创建更多需要的对象或使东西过于复杂的情况下,我可以做些什么来完成这项工作......

【问题讨论】:

    标签: c++ class nested


    【解决方案1】:

    添加几个构造函数和一个指向父类的指针。

    #include <string>
    #include <vector>
    class myList
    {
    public:
        std::vector<std::string> vec;
        myList(): items(this) {} // Added
        class Items
        {
        public:
            Items(myList *ml): self(ml) {}  // Added
            void Add(std::string str)
            {
                    self->vec.push_back(str); // Changed
            };
            myList *self; //Added
        }items;
    };
    
    int main()
    {
        myList newList;
        newList.items.Add("A");
    }
    

    您需要 myList() 构造函数,因此它将自身的实例注册到内部类成员变量的实例中。然后,您需要 Items 构造函数来存储指向外部 myList 类实例的指针。最后在 Add 方法中,需要在存储的 myList 实例中引用 vec。

    正如 Catskul 所指出的,Item 构造函数实际上不能对它接收到的 myList 指针做任何事情。我还想说,虽然这个答案更接近初衷,但 steveth45 的答案更接近你在真实程序中想要做的。

    【讨论】:

    • 非常感谢,这行得通,但我希望存在一个更简单的版本,但我必须继续应对 C++ 的顽固:-(希望 C++0x 解决其中的一些怪癖
    • ... 但是在 MyList 仍在构建时要小心传递 MyList 这个指针。如果 Items 构造函数做的任何事情最终过早地使用了 MyList this 指针,它就会陷入麻烦。
    【解决方案2】:

    这样您就不会直接暴露您的班级成员。你的例子似乎有点过度架构。为什么将 std::vector 放入一个类中,然后将其公开?

    class myList
    {
    private:
        std::vector<std::string> vec;
    public:
        void Add(std::string str)
        {
            vec.push_back(str);
        };
    };
    
    int main()
    {
        myList newList;
        newList.Add("A");
    }
    

    【讨论】:

    • 原作者可能需要内部类构造来处理他没有提到的其他内容(为了他的说明简单)。鉴于现有信息,您对软件工程软方面的看法是正确的,但问题似乎是一个抽象编译问题的“玩具”,因为最初可能是一个非常复杂的算法。真的不重要,你可能已经明白了,我只是说......
    【解决方案3】:

    与 Java 不同,C++ 中的内部对象无法访问外部“this”指针...如果您考虑一下,可能存在没有可引用的情况。

    Richard Quirk 的解决方案是 C++ 中最接近的解决方案

    【讨论】:

      【解决方案4】:

      内部类仅按名称相关。你不能这样引用基类中的向量。

      您要么需要将向量移入内部类,要么存储对它的引用。

      【讨论】:

        【解决方案5】:

        虽然这篇文章已经有几年了,但我可能可以添加一些有用的东西。虽然我会说原始帖子中类的设计看起来不太好,但有时让嵌入式类能够访问包含类是很有用的。这可以很容易地完成,而无需存储额外的指针。下面是一个例子。它应该可以工作,因为我从一些现有代码中获取它并更改了一些名称。关键是 EmbeddorOf 宏。像魅力一样工作。

        /////////////////.h 文件 ///////////////////// /

        struct IReferenceCounted
        {
            virtual unsigned long AddRef() = 0;
            virtual unsigned long Release() = 0;
        };
        
        struct IFoo : public IReferenceCounted
        {
        };
        
        class Foo : public IFoo
        {
        public:
            static IFoo* Create();
            static IFoo* Create(IReferenceCounted* outer, IReferenceCounted** inner);
        
        private:
            Foo();
            Foo(IReferenceCounted* outer);
            ~Foo();
        
            // IReferenceCounted
        
            unsigned long AddRef();
            unsigned long Release();
        
        private:
            struct EIReferenceCounted : IReferenceCounted
            {
                // IReferenceCounted
        
                unsigned long AddRef();
                unsigned long Release();
            } _inner;
        
            unsigned long _refs;
            IReferenceCounted* _outer;
        };
        

        //////////////.cpp 文件/////////////////

        #include <stdio.h>
        #include <stddef.h>
        #include "Foo.h"
        
        #define EmbeddorOf(class, member, this) \
            (class *) ((char *) this - offsetof(class, member))
        
        // Foo
        
        Foo::Foo() : _refs(1), _outer(&this->_inner)
        {
        }
        
        Foo::Foo(IReferenceCounted* outer) : _refs(1), _outer(outer)
        {
        }
        
        Foo::~Foo()
        {
            printf("Foo::~Foo()\n");
        }
        
        IFoo* Foo::Create()
        {
            return new Foo();
        }
        
        IFoo* Foo::Create(IReferenceCounted* outer, IReferenceCounted** inner)
        {
            Foo* foo = new Foo(outer);
            *inner = &foo->_inner;
            return (IFoo*) foo;
        }
        
        // IReferenceCounted
        
        unsigned long Foo::AddRef()
        {
            printf("Foo::AddRef()\n");
            return this->_outer->AddRef();
        }
        
        unsigned long Foo::Release()
        {
            printf("Foo::Release()\n");
            return this->_outer->Release();
        }
        
        // Inner IReferenceCounted
        
        unsigned long Foo::EIReferenceCounted::AddRef()
        {
            Foo* pThis = EmbeddorOf(Foo, _inner, this);
            return ++pThis->_refs;
        }
        
        unsigned long Foo::EIReferenceCounted::Release()
        {
            Foo* pThis = EmbeddorOf(Foo, _inner, this);
            unsigned long refs = --pThis->_refs;
            if (refs == 0)
                {
        
                // Artifically increment so that we won't try to destroy multiple
                // times in the event that our destructor causes AddRef()'s or
                // Releases().
        
                pThis->_refs = 1;
                delete pThis;
                }
            return refs;
        }
        

        尼克

        【讨论】:

          【解决方案6】:

          您可以通过以下构造来简化它:

          typedef std::vector<std::string> myList;
          

          真的为什么不直接使用 STL 向量呢? 通过这种方式,您可以获得所有标准算法 数据。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2017-11-02
            • 2011-05-30
            • 2012-11-02
            • 2020-11-13
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多