1

I want to create two base class that cannot be instantiated. I wrote the code as below, but it gave a compile error.

class Test {
std::string x_;
public:
    Test(std::string x): x_{x} {}
};

class BaseCompartment {
    Test x_;
protected:
    BaseCompartment(Test x): x_{x} {}
    virtual ~BaseCompartment() = 0;
    
    const Test& getTest1() const {
        return x_;
    }
}; 

class BaseTempCompartment: public BaseCompartment {
    Test y_;
protected:
    BaseTempCompartment(Test x, Test y): y_{y}, BaseCompartment(x) {}
    virtual ~BaseTempCompartment() = 0;
    
    const Test& getTest2() const {
        return y_;
    }  
}; 

class XTempCompartment: public BaseTempCompartment {
public:
    XTempCompartment(Test x, Test y): BaseTempCompartment(x, y) {}
    ~XTempCompartment() {}
};

int main() {
    XTempCompartment x {Test("1"), Test("2")};

    return 0;
}

I'm sure there are tons of errors in the code above.

The BaseCompartment and BaseTempCompartment classes contain a variable(Test).

I want to use these Test classes in the XTempCompartment class by calling getTest1() and getTest2().

My goal is not to let BaseCompartment and BaseTempCompartment classes be instantiated.

Do I have to call it in abstract like below to create the Test class?

BaseCompartment(Test x): x_{x} {}

Also Is the correct usage for getting test variables like below?

const Test& getTest1() const {
    return x_;
}

How can I make the above code executable?

How can I write the above code better for these purposes?

  • 3
    Make all constructors protected and its destructor virtual – Pepijn Kramer Jul 28 '23 at 09:15
  • 1
    See also: https://stackoverflow.com/questions/630950/pure-virtual-destructor-in-c – UnholySheep Jul 28 '23 at 09:16
  • 1
    Assuming you didn't forget to implement the destructors, [fix these warnings](https://godbolt.org/z/qe5dnPzK5) and it seems ok. – pptaszni Jul 28 '23 at 09:22
  • Pure virtual destructor is a problem: https://godbolt.org/z/1cfb3P69Y droping `= 0` fixes issue (it is possibloe to have it as pure virtual destructor, but it is unusual and should not be practiced). – Marek R Jul 28 '23 at 09:39
  • A pure virtual destructor must still be defined, since destruction of any instance of a derived class implicitly calls base class destructors (whether they are pure virtual or not). In general, a class cannot be instantiated if it either declares a pure virtual function or has a base with a pure virtual (non-destructor) function that it doesn't override. – Peter Jul 28 '23 at 10:16
  • @Peter ```A pure virtual destructor must still be defined```. I didn't understand exactly why we had to write as pure virtual. Because doesn't it do the same job in virtual destructor(not pure)? – Metropol_Tilkisi Jul 28 '23 at 10:20
  • A pure virtual destructor can be used to ensure the class itself cannot be instantiated (even if, for example, it is a derived class that overrides all pure virtuals that it inherits, but it serves as a base for other [presumably instantiable] classes and we still don't want to instantiate it). – Peter Jul 28 '23 at 10:24
  • @Peter Adding ```BaseCompartment ::~BaseCompartment () {}``` and ```BaseTempCompartment::~BaseTempCompartment() {}``` after the class decleration makes code OK, right? – Metropol_Tilkisi Jul 28 '23 at 11:28

1 Answers1

0

U should make constructors protected, so u can access them only from instances of inherited classes.

And u make destructors virtual, so the it gets destroyed when u destroy instances of inherited classes.

  • 1
    Making constructors `protected` only prevents unrelated classes or functions from instantiating the class. Derived classes, `friend`s, and member functions of the class itself can still instantiate classes that have protected constructors (unless the class has one or more pure virtual functions). – Peter Jul 28 '23 at 10:20