3

I am a learner of C++. I have compiled the below program. I am working on constructors and destructors concept. I have this code here below where I declare a private destructor and access the private members using member function of the class from main(). I know that a private constructor can be declared but is a public constructor also mandatory? here is my code below:

class Book
{
private:
    int *pages;
    int *price;


    Book()        //default constructor
    {
        pages = new int;
        price = new int;
        *pages = 300;
        *price = 8;
    }

public:
    void pre_destructor()
    {
        std::cout << "The pages:" << *pages << "\n";
        std::cout << "The price:" << *price << "\n";
    }

~Book() //destructor
    {
        std::cout << "The pages:" << *pages << "\n";
        std::cout << "The price:" << *price << "\n";
        delete pages;
        delete price;
    }

};

int main()
{
    using namespace std;
    Book book1;

    cout << "Before using destructors" << endl;
    cout << "---------------------------------"<< endl;

    book1.pre_destructor();

    cout << "After using destructors" << endl;
    cout << "---------------------------------";

    return 1;

}

For the above program, two errors are shown. One is in the main function where an object is declared; Error: error within content. And the second one is in the line where the constructor is called; Error:Book::Book() is private.

The main is not directly accessing the constructor in the code. Then why does it shows the access error?

Kiran C K
  • 67
  • 7
  • 1
    declaring constructor as private wont let the object be created, in other scopes. As the constructor cant be called from there. so constructor/destructor is made public! – Sagar Kar Nov 21 '15 at 05:25
  • 2
    You need to get [a good book](http://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list). – T.C. Nov 21 '15 at 05:26
  • 3
    `The main is not directly accessing the constructor in the code.` Is too. The line `Book book1;` initializes the object using its default constructor (which you made private and thus inaccessible). – Igor Tandetnik Nov 21 '15 at 05:28
  • stop using new & delete. Is dynamic memory allocation is really required here? main should return 0. why are you accessing the data members from destructor? – Destructor Nov 21 '15 at 05:55
  • 1
    @PravasiMeet: Not that there is anything wrong in accessing data members in the destructor... – Matthieu M. Nov 21 '15 at 16:24
  • @MatthieuM.: yes, you are right. But why would someone want to access data members in the destructor.? – Destructor Nov 21 '15 at 16:42

3 Answers3

7

No, a public constructor is not mandatory. There are use cases for private constructors.

  • A class with only static methods might have private (or deleted) constructors to prevent instances being created.
  • A singleton class (where only one instance of the class exists) might enforce its singleton status by having a private constructor. That instance can be accessed through a static getter.
  • You might want to follow a builder or factory pattern, where you force your users to construct instances using a process beside calling the constructor. That builder or factory would be either a member of the class or a friend, so able to call a private constructor. This scheme is much more common in Java than C++, but C++ allows it as well.

That said, you're looking to simply construct an instance of a class:

Book book1;

This use definitely requires a public default constructor.

Adam
  • 16,808
  • 7
  • 52
  • 98
2

When you make a constructor private, you need to expose a method so that external classes/methods can create object of this class. You'd do so by creating a static method, which in turn creates the object.

following code demonstrates:

#include <iostream>
class Book
{
private:
    int *pages;
    int *price;


    Book()        //default constructor
    {
        pages = new int();
        price = new int();
        *pages = 300;
        *price = 8;
    }

public:
    static Book* constructBook() 
    {
        return new Book();
    }

    void pre_destructor()
    {
        std::cout << "The pages:" << *pages << "\n";
        std::cout << "The price:" << *price << "\n";
    }

    ~Book() //destructor
    {
        delete pages;
        delete price;
    }

};

int main()
{
    Book* book1 = Book::constructBook();

    std::cout << "Before using destructors" << endl;
    std::cout << "---------------------------------"<< endl;

    book1->pre_destructor();

    cout << "After using destructors" << endl;
    cout << "---------------------------------";
    delete book1;
    return 0;

}
Destructor
  • 14,123
  • 11
  • 61
  • 126
Nandu
  • 808
  • 7
  • 10
1

Not at all ! You don't need a public constructor but you need a factory fuction to create an instance of that class & in that case you need to qualify that function with the keyword static. See below :-

#include <iostream>
using namespace std;
class X
{
    int x;
    X(int x)
    { 
        cout<<"creation\n";
        this->x = x; 
    }
    public:
    static X make_X (int x) // without static error message will be : error: cannot call member function 'X X::make_X(int)' without object
    {
        return X(x);
    }
    int& getx()
    {
        return x;
    }
    ~X()
    {
        cout<<"destruction\n";
    }
};
int main()
{
    auto obj = X::make_X(5);
    auto ano = X::make_X(7);
    cout << obj.getx() << '\t' << ano.getx() << '\n';
    return 0;
} 

Output is :-

creation
creation
5   7
destruction
destruction

There is no need of a public contrcutor here. But you needed make_X to create an instance of the class.

You can also use friend instead of static. In that case the code will be :-

friend X make_X (int x);  // declare a prototype in the class

Then define outside the class definition :-

X make_X (int x)
{
    return X(x);
}

That's how it works ! Cheers!!

DevInd
  • 1,645
  • 2
  • 11
  • 17