std :: map <my_enum,base_class =“”>插入错误:base_class是derived_class的不可访问的基础

时间:2018-07-19 10:37:38

标签: c++11

这个小程序必须编写一个xml文件。 构建代码时,出现以下错误: K:\Sergio\cpp\xml\sergio\cbp6s\main.cpp|32|error: 'base_tag' is an inaccessible base of 'tag'
简而言之,我有两个派生自base_tag的类(xml_declaration和tag),我想在std :: map中插入(或放置)一些std :: pair元素。
构建时,第一个插入有效(std::pair<order::declaration, xml_declaration>),但是第二个插入失败(std::pair<order::root, tag_object>)。
对象之间是从base_tag派生的
我在哪里错了?

文件tag.hpp

#ifndef _TAG_HPP_
#define _TAG_HPP_

#include <string>
#include <vector>
#include <utility>

enum class tag_type
{
    closing = -1,
    autoclosed = 0,
    opening  = 1
};

using attribute = std::pair<std::string, std::string>;

class base_tag
{
public:
    base_tag();
    virtual ~base_tag();

    virtual std::string get();
    bool attribute_exists(std::string);
    std::string get_attribute_value(std::string name);
    bool add_attribute(std::string name, std::string value);

protected:

    std::vector<std::pair<std::string, std::string>> _attributes;
};

// ------------------------------------------------------------ 

class xml_declaration : public base_tag
{
public:
    xml_declaration();
    ~xml_declaration();
    std::string get();
};

// ----------------------------------------------------------

class tag : base_tag
{
public:
    tag(std::string name);
    tag(std::string name, tag_type tt );
    std::string get();
    void set_ident(size_t ident);

protected:
    std::string _name;
    tag_type _tt;
};

#endif // _TAG_HPP_

文件tag.cpp

#include "tag.hpp"

base_tag::base_tag()
{
}

base_tag::~base_tag()
{
    _attributes.clear();
}

bool base_tag::attribute_exists(std::string name)
{
    bool res = false;

    for(auto & i : _attributes)
    {
        if (i.first == name)
            res = true;
    }

    return res;
}

bool base_tag::add_attribute(std::string name, std::string value)
{
    bool res = false;

    if(!attribute_exists(name))
    {
        attribute a = std::make_pair(name, value);
        _attributes.push_back(a);
        res = true;
    }
    return res;
}

std::string base_tag::get()
{
    return u8"<invalid_tag/>";
}

// -------------------------------------------------------

xml_declaration::xml_declaration(): base_tag()
{
    add_attribute("version", "1.0");
    add_attribute("encoding", "UTF-8");
    add_attribute("standalone", "yes");
}

xml_declaration::~xml_declaration()
{ }

std::string xml_declaration::get()
{
    std::string res = u8"<?xml";
    for(auto & i : _attributes)
    {
        res.push_back(' ');
        res += i.first;
        res += u8"=\"";
        res += i.second;
        res += u8"\"";
    }
    res += u8" ?>";
    return res;
}

// -------------------------------------------------------------

tag::tag(std::string name):base_tag(), _name(name)
{
    _tt = tag_type::autoclosed;
}

tag::tag(std::string name, tag_type tt ): base_tag(), _name(name), 
_tt(tt)
{ }

std::string tag::get()
{
    std::string res = u8"";

    bool with_attributes = !(_attributes.empty());
    switch(_tt)
    {
        case tag_type::autoclosed : {    
            res = u8"<";
            res += _name;
            if(with_attributes)
            {
                for(auto & i : _attributes)
                {
                    res.push_back(' ');
                    res += i.first;
                    res += u8"=\"";
                    res += i.second;
                    res += u8"\"";
                }
            };
                    res += u8"/>";
                    break;
        }

    case tag_type::opening :   {   
                    res = u8"<";
                    res += _name;
                    for(auto & i : _attributes)
                    {
                        res.push_back(' ');
                        res += i.first;
                        res += u8"=\"";
                        res += i.second;
                        res += u8"\"";
                    }
                        res += u8">";
                        break;
                            }

    case tag_type::closing :  {   
                        res = u8"</";
                        res += _name;
                        res.push_back('>');
                        }

    default :           break;

    }
    return res;
}

文件main.cpp

#include <iostream>
#include <map>
#include <utility>
#include "tag.hpp"

using namespace std;

enum class order
{
    declaration     = 0,
    root            = 1,
    file_version    = 4,
    project         = 10,
    project_closing = 998,
    root_closing    = 1000
};

int main()
{
    std::map<order, base_tag> tree;

    xml_declaration decl;
    cout << decl.get() << endl;

    tag t1("project_file", tag_type::opening);
    tag t2("project_file", tag_type::closing);

    tree.insert(std::pair<order, base_tag>(order::declaration, 
decl));
    tree.insert(std::pair<order, base_tag>(order::root, t1));
    tree.insert(std::pair<order, base_tag>(order::root, t2));
//  tree.emplace(std::pair<order, base_tag>(order::root_closing, t1));

    cout << tree.size() << endl;

    return 0;
}

我在GCC 5.1.0(在Windows 10上)上使用Code :: Blocks。

1 个答案:

答案 0 :(得分:1)

如错误消息所述,tag是秘密继承base_tag的。如果将其标题更改为

class tag: public base_tag;

(与您的xml_declaration公开继承base_tag一样),它将正式成为基本标记。

一个更严重的问题是,您尝试按值将继承的类的实例存储在基类的容器中。然后发生的是,对象被切成薄片并失去了它们的全部派生功能。您将派生类的对象放入映射中,但实际上在其中存储了基类的对象(这就是某些人倾向于说多态基类必须一定是抽象的原因。)使用(智能)指针或{{ 1}}是reference_wrapper的映射类型。