Make sure that all constructors call same function c++, design pattern

Viewed 57

Let us assume that we have a class called Node which has a member called sequence and id. We want to print the sequence of the Node in many differnt ways. Instead of adding the print functions directly into the Node class, we put them into a seperate class called NodePrinter. Each Node, needs to have a "working" NodePrinter in any case.

Which implies that:

  1. Node has a NodePrinter * printer member

  2. Every constructor of Node needs to create a new NodePrinter

My idea now was to create a BaseNode and move the NodePrinter into that one. It has only one constructor, which takes a Node as an input and assigns it to the NodePrinter:

#include <iostream>
#include <string>

using namespace std;

class NodePrinter;
class Node;
class BaseNode
{
public:
    BaseNode() = delete;
    BaseNode(Node * node);
    ~BaseNode();

    NodePrinter * printer;
};

class Node: public BaseNode
{
public:
    Node(string sequence): BaseNode(this), sequence(sequence){}
    Node(int id, string sequence): BaseNode(this), sequence(sequence), id(id){}

    int id;
    string sequence;
};

class NodePrinter
{
private:
    Node * node;

public:
    NodePrinter() = delete;
    NodePrinter(Node * node): node(node){}
    void print_node()
    {
        std::cout<<node->sequence<<endl;
    }
};

BaseNode::BaseNode(Node * node)
{
    node->printer = new NodePrinter(node);
}

BaseNode::~BaseNode()
{
    delete printer;
    printer = nullptr;
}



int main()
{
    Node node("abc");
    node.printer->print_node();
    return 0;
}

Thereby each node is forced to call BaseNode(this) and the resources get allocated.

Is this reasonable, or is this whole approach already twisted from the start? Is there a better way to do this?

1 Answers

One thing that seems odd to me is that the printer depends on an instance of Node, shouldn't it be possible for a single printer to print multiple nodes? And I also wouldn't have Node depend on a NodePrinter either, because then you can't print the same node with multiple printers.

Anyhow, if you really need to keep the 1-to-1 correspondence, the simplest way is to just initialize the NodePrinter directly where the member variable is declared in Node:

#include <iostream>
#include <memory>
#include <string>

class Node;

class NodePrinter
{
private:
    Node * node;

public:
    NodePrinter() = delete;
    NodePrinter(Node * node): node(node){}

    void print_node();
};

class Node
{
public:
    Node(std::string sequence) : sequence(std::move(sequence)){}
    Node(int id, std::string sequence) : id(id), sequence(std::move(sequence)) {}

    int id;
    std::string sequence;

    std::unique_ptr<NodePrinter> printer = std::make_unique<NodePrinter>(this);
};

void NodePrinter::print_node()
{
    std::cout<< node->sequence << '\n';
}

int main()
{
    Node node("abc");
    node.printer->print_node();
    return 0;
}

Live demo on wandbox.

Related