Reputation: 1485
I have 4 classes
class A { //a base class
public:
A(ostringstream* os){ oss2=os; }
ostringstream* oss2;
};
class B : public A{ // a derived class
public:
B(ostringstream* os):A(os){};
};
class C { //class where oss is actually declared
public:
C(){};
ostringstream oss;
};
and finally (the kicker): a derived class from "C" , that needs to pass a reference to oss
around.
class D : public C{
public:
B b(&oss);
};
in line B b(&oss);
I get the error
error: expected identifier before ‘&’ token
I honestly don't know if I am playing with fire here. The basic idea is that I want some functions of A to write to a common output stream.
This is not a logging class but I see that some loggers declare a static oss variable and allow everyone to write there. I would prefer to avoid that and instantiate my oss in the (logically) correct location. In my case, that is in class C.
I think (but I could be wrong) that the error here is that I am trying to provide a reference to a variable (oss) through the declaration of B b
. Is that right? Instead an initializer list should be used to provide the value to the constructor. But I am not sure how to implement this (and test if it compiles).
Upvotes: 0
Views: 86
Reputation: 9232
If you want to have a field of type B
in D
, you should just declare it there and initialize it in the constructor, as you already hinted at:
class D : public C{
public:
D() :
C(), // You can leave this out, the compiler will do it for you
b(&oss) // Once the C part is constructed you can pass in its field.
{}
private: // ?
B b;
};
But depending on your situation, there may be a better solution in terms of design. For example, if C
is a base class for output, and A
is a class that needs to do some logging, you could go with a solution like this:
class A { // worker base class
public:
A(C* logger) : logger(logger) {}
private:
C* logger;
};
class B : public A{ // a derived class
public:
B(C* logger) : A(logger) {};
};
class C { // logging class
public:
C(){};
virtual ~C() {};
virtual void Log(const std::string& message) = 0;
};
class D : public C { // a derived class
public:
D() {}
virtual void Log(const std::string& message)
{
this->oss << message;
}
private:
ostringstream oss;
}
// In main:
D streamLogger;
A worker(&streamLogger);
Now A
doesn't care what it outputs to, just pass it a class which supports Log
ging a message and let polymorphism handle the rest. In fact, if you want to have a logging method that sends emails, just create a new derivative of C
and pass it into the same A
instance.
Upvotes: 2
Reputation: 9602
You need to properly declare a B
data member and then construct is properly.
class D : public C
{
public:
B b; // Declare a 'B' type
// 'B' must be instantiated with a single argument therefore it must be
// constructed in the initializer list
D() : b(&oss) {}
};
Upvotes: 2