Reputation: 2664
I asked this question here: C++ Method chaining with classes
In essesance, what I am trying to do is call a Constructor/Method from another class using Method chaining. Let's say I have 2 classes:
class Signal {
public:
Signal() { } // constructor
Signal& ParseSignal() {
// In this method I want to call
// the constructor "Parse()"
}
protected:
std::vector<double> data;
};
And I have another class called Parse
:
class Parse {
public:
Parse() {
// This is the implementation
// I need to access the "data" contained in class "Signal
};
My main objective would be to do the following in main:
Signal s = Signal().ParseSignal();
This would then accept the signal, and, Parse this.
Someone suggested that I should use CRTP
however, due to the fact that the base class (in this case Signal
) has to have a template<>
argument, this is not possible due to other classes inheriting.
Is there another solution to this problem?
EDIT:
I have tried the following, however, it looks like a dirty
implementation and I cannot access the member variable:
class Parser {
public:
Parser() {
parse();
}
void parse() {
cout << "YES";
}
};
class Signal {
public:
friend class Parser;
Signal() { val = 0;}
Signal& Parse() {
Parser::Parser();
return *(this);
}
protected:
int val;
};
Upvotes: 0
Views: 12555
Reputation: 24249
You implicitly cannot and should not do what you appear to be trying to do, which is to call the constructor of a class without constructing an instance of the class.
If you want the behavior of Parser in Signal, then you have at least three options: 1. Inherit Parser, 2. Add a Parser member, 3. Create a "Parseable" interface-class which Parser can take as an argument.
class Parser {
public:
class Interface {
public:
std::vector<double> m_data;
};
Parser(Interface& interface) {
parse(interface);
}
};
class SignalInheriting : public Parser::Interface {
public:
SignalInheriting() {
Parser p(*this); // can take the Parser::Interface view of this object.
}
};
class SignalMember {
Parser::Interface m_parserIface;
public:
SignalMember() : m_parserIface() {
}
};
Doing heavy lifting in constructors like this is great for obfuscated or dog-show code, but is terrible for production systems that require any kind of maintenance.
But if you're fine with having to diagnose problems in code that works hands-free like this at 3am on a Saturday when you're hung over - then go for it.
A major factor to which pattern you should choose is how long the parse-related data is going to persist vs how long the Signal objects are going to persist.
Conversely, if the Signal object is little more than a specialization of the "Parse" API, then just inherit Parse and be done with.
Upvotes: 4
Reputation: 5135
The simplest way to do what you are trying to do would be something like this:
class Parse {
public:
Parse(std::vector<double> &data) {
// do stuff
}
};
class Signal {
public:
Signal() { } // constructor
Signal& ParseSignal() {
Parse parser(data);
return *this;
}
protected:
std::vector<double> data;
};
However I suggest that you take a look at the Visitor Pattern for a more generic solution.
Or at the very least don't do the work in the Parse constructor, do it in some method instead.
Upvotes: 3