【问题标题】:Protected issue with method in class类中方法的受保护问题
【发布时间】:2020-11-07 00:09:10
【问题描述】:

我有一个带有嵌套类的 Request_manager 类:

class Request_manager {
    public:
        class Ticket {
        protected:
            explicit Ticket(System_time start_time);
            virtual void start() = 0;
        }
        struct ticket_element_{
            int app;
            std::shared_ptr <Ticket> ticket;
        };
    
        class Tickets_Queue{
        private:
            std::queue <ticket_element_> m_queue;
    
        public:
            void push(ticket_element_ ticket);
        };
    };

Request_manager::Ticket 是其他类的父类,例如Ticket,它们有自己的start() 实现:

class Ticket : public Request_manager::Ticket,
               public std::enable_shared_from_this<Ticket> {
    void start();
};

ticket_element_ 可以保存来自Request_manager::Ticket 的不同孩子。在Request_manager::Tickets_Queue::push的执行中我这样做:

void Request_manager::Tickets_Queue::push(ticket_element_ ticket_container){
    run_async(ticket_container.app, async::Policy::FIFO,
        [ticket_container]() { ticket_container.ticket->start(); });
}

我得到错误:

In file included from data_interfaces/Request_manager.cpp:1:0:
data_interfaces/Request_manager.h: In lambda function:
data_interfaces/Request_manager.h:31:22: error: ‘virtual void dataserver::Request_manager::Ticket::start()’ is protected
         virtual void start() = 0;
                      ^
data_interfaces/Request_manager.cpp:66:67: error: within this context
             [ticket_container]() { ticket_container.ticket->start(); });

我不明白,因为一旦我有了对象,我应该能够访问受保护的方法

【问题讨论】:

  • 为什么你认为Request_manager::Tickets_Queue 应该能够访问Request_manager::Ticket 的受保护成员?
  • "我忘了说 Ticket 是 Request_manager 的子类" 那么请出示你的真实代码:minimal reproducible example
  • @HectorEsteban 这完全不相关。 Request_manager::Tickets_Queue 不继承自 Request_manager::Ticket,因此,它不能调用其受保护的成员函数。
  • @HectorEsteban 实际上,你是。您正在尝试从 Request_manager::Tickets_Queue::push 调用受保护的成员函数。
  • @HectorEsteban 不,不应该。除了Ticket 类型的对象,你怎么能调用start?在这里没关系。

标签: c++ nested virtual protected


【解决方案1】:

ticket_container.ticket-&gt;start(); 中,您试图从共享指针访问受保护的方法,该指针在基类Request_manager::Ticket 中无法访问它,因此它无法应用vtable

如果您将Request_manager::Ticket 中的protected 更改为public,它将起作用,因为它可以访问该方法并应用vtable,从而调用派生的Ticket

我已经添加/更改了一些以便能够重现:

class Request_manager
{
public:
    class Ticket {
    protected:
        explicit Ticket() {}
        ~Ticket() {}
    public:
        virtual void start() = 0;
    };
    struct ticket_element_{
        int app;
        std::shared_ptr <Ticket> ticket;
    };
    
    class Tickets_Queue{
    private:
        std::queue <ticket_element_> m_queue;
    
    public:
        void push(ticket_element_ ticket);
    };

    Tickets_Queue _queue;
};

class Ticket : public Request_manager::Ticket,
                 public std::enable_shared_from_this<Ticket>
{
public:
    void start() {
        cout << "Starting ticket" << endl;
    }
};


void Request_manager::Tickets_Queue::push(ticket_element_ ticket_container){
    ticket_container.ticket->start();
}


int main() {
    Request_manager rm;

    rm._queue.push ({0, make_shared<Ticket>()});
    
    return 0;
}
manuel@desktop:~/projects$ g++ -Wall -Wextra -g main.cc -o main --std=gnu++2a -Wpedantic && time ./main
Starting ticket

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-05-02
    • 2013-04-06
    • 1970-01-01
    • 2020-07-26
    • 2011-01-15
    • 2017-12-14
    • 1970-01-01
    • 2014-05-01
    相关资源
    最近更新 更多