0

I have a compilation error with C++11.

I have defined a base class Node with protected ctor and dtor. I have defined an inherited class Directory with public inheritance.

I am calling the dtor of the base class in the dtor of the inherited class. The compilation failed with the message:

error: 'virtual Node::~Node()' is protected within this context

I really don't understand why, as I was pretty sure that the protected keyword allowed methods (and objects) in a derived class to have access to public and protected methods (and data) of the base class.

Below I have put the code, that I hope has enough comments. The idea is to create a basic fs running in RAM.

Node.hpp

#ifndef NODE_HPP
#define NODE_HPP

#include "FileSystem.hpp"

class Directory;    //Forward declaration of class Directory used in this class
class File;         //Forward declaration of class File used in this class

/*Class representing a node of the fs : a node can be a file or a directory*/
class Node
{
    /*friend class Directory;*/     //Related to the issue #1 : Destructor protected within this context

    protected:
        Node(FileSystem *, int, string, Directory * = nullptr);
        virtual ~Node();
        Node(const Node&);

    ...

#endif // NODE_HPP

Node.cpp

#include "Node.hpp"

Node::Node(FileSystem *fs, int uid, string name, Directory *parent) {
    this->fs = fs;
    this->uid = fs->get_fresh_uid();
    this->name = name;
    this->parent = parent;
}

Node::~Node(){
    fs = nullptr;
    parent = nullptr;
}

...

Directory.hpp

#ifndef DIRECTORY_HPP
#define DIRECTORY_HPP

#include "Node.hpp"
#include "File.hpp"
#include <vector>

/*Class representing a directory of the fs : a directory is a kind of node*/
class Directory : public Node
{
    /*friend class FileSystem;*/ //Related to issue #2 : forward declaration of class Directory

    private:
        Directory(FileSystem *fsys, int id, string n, Directory *par = nullptr);
        virtual ~Directory();
        Directory (const Directory &);
    private:
        vector<Node*> children;             //Vector representing the children nodes of the directory
    ...
};

#endif // DIRECTORY_HPP

Directory.cpp

#include "Directory.hpp"

Directory::Directory(FileSystem *fs, int uid, string name, Directory *parent) : Node(fs, uid, name, parent){
}

Directory::~Directory(){
    for (auto c : children) {
        delete c;   //Related to the issue #1 : Destructor protected within this context
        c=nullptr;
    }
}

...
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
infoasker
  • 17
  • 2
  • 4
    `delete` isn't just a keyword, it is a function as well. that function does not have access to any protected or private members. – NathanOliver May 03 '22 at 18:02
  • 1
    please read about [mcve]. A mininal example that reproduces the issue needs only two classes and a destructor, not all the other methods – 463035818_is_not_an_ai May 03 '22 at 18:03
  • Thanks for your quick answer, and sorry if the question was basic. Then, how to call the dtor of the base class without delete ?? – infoasker May 03 '22 at 18:04
  • OK for minimal examples, thanks – infoasker May 03 '22 at 18:06
  • I don't remeber to have seen a use case for a `protected` destructor. Is there some reason you dont make it `public`? – 463035818_is_not_an_ai May 03 '22 at 18:07
  • This doesn't address the question, but `fs = nullptr;` and `parent = nullptr;` in the `Node` destructor don't accomplish anything. The `Node` object is going away, and its members will not be accessible after the destructor finishes. – Pete Becker May 03 '22 at 18:08
  • @infoasker _"(issue #1)"_ are you planning to ask a series of questions now until all your issues with that code are fixed?? Please don't! – πάντα ῥεῖ May 03 '22 at 18:11
  • The reason of protected is for an "external user" be unable to create or delete a node. – infoasker May 03 '22 at 18:11
  • Actually I have only 2 questions : is that acceptable ? – infoasker May 03 '22 at 18:12
  • 1
    if they cannot create an instance then there is no need to prevent them from deleting it. – 463035818_is_not_an_ai May 03 '22 at 18:13
  • I have edited the post to reduce the example code, hope it helps. – infoasker May 03 '22 at 18:14
  • Should I overload the delete operator anywhere ? – infoasker May 03 '22 at 18:18
  • @NathanOliver That's a weird way to put it. If you mean `operator delete()`, then it's just a glorified `free()` that doesn't know anything about specific classes. – HolyBlackCat May 03 '22 at 18:31
  • @HolyBlackCat yes a friendship is more simple (for me) – infoasker May 03 '22 at 18:35
  • fwiw, this is a minimal example of the issue https://godbolt.org/z/j13GdchaW and the duplicate explains why it is an error – 463035818_is_not_an_ai May 03 '22 at 18:35
  • @463035818_is_not_a_number Thanks you learned me several things : the meaning of fwiw, the godbolt site and the answer of my first question – infoasker May 03 '22 at 18:41
  • @NathanOliver Are you sure about `delete` being a function? Afaik `delete` is an operator. An operator that may result in the invokation of the destructor, but not a function. Starting C++20 there may be an operator responsible for the invokation of the destructor, but this is optional. – fabian May 03 '22 at 18:42
  • @NathanOliver "it is a function as well. that function does not have access to any protected or private members." I don't think this is right. If it was this would be an error too: https://godbolt.org/z/hKxoqjPfq. The issue is that the derived cannot access protected members of a base instance. – 463035818_is_not_an_ai May 03 '22 at 18:43
  • 1
    @HolyBlackCat and fabian, it was a gross oversimplification. I was just trying to convey that it was `delete` that needs access to the destructor, and it doesn't get that automatically to protected and private members. – NathanOliver May 03 '22 at 18:44
  • @NathanOliver 463035818_is_not_a_number and fabian thanks for the explanations – infoasker May 03 '22 at 18:49

1 Answers1

-1

Thanks for the comments and the link to the answer.

infoasker
  • 17
  • 2
  • I think nathan was wrong. It they were right then this would be an error as well: https://godbolt.org/z/hKxoqjPfq but it isnt. – 463035818_is_not_an_ai May 03 '22 at 18:38
  • @463035818_is_not_a_number So the correct answer is "protected destructor can only be used to destroy a base class subobject" ? My english fails me : why base clas SUBobject and not object ? – infoasker May 03 '22 at 18:46
  • honestly I wouldn't spent to much time on this but rather make the destructor public and call it a day. On the other hand, digging into details of C++ may learn you some useful stuff even if a protected destructor isnt that useful ;) – 463035818_is_not_an_ai May 03 '22 at 18:48
  • @463035818_is_not_a_number OK no problem – infoasker May 03 '22 at 18:51