混合 c++ class 继承和初始化列表。我心中的未解之谜
mixing c++ class inheritance and initializer lists. An unsolved puzzle in my mind
我有 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;
};
最后(踢球者):从 "C" 派生的 class ,需要传递对 oss
的引用。
class D : public C{
public:
B b(&oss);
};
在行 B b(&oss);
我收到错误
error: expected identifier before ‘&’ token
老实说,我不知道我在这里是不是在玩火。基本思想是我希望 A 的一些函数写入一个公共输出流。
这不是日志记录 class 但我看到一些记录器声明了一个静态 oss 变量并允许每个人在那里写入。我宁愿避免这种情况,并在(逻辑上)正确的位置实例化我的 oss。就我而言,那是在 class C.
我认为(但我可能是错的)这里的错误是我试图通过 B b
的声明提供对变量 (oss) 的引用。那正确吗?相反,应该使用初始化列表来为构造函数提供值。但是我不确定如何实现它(并测试它是否编译)。
如果你想在 D
中有一个 B
类型的字段,你应该在那里声明它并在构造函数中初始化它,正如你已经暗示的那样:
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;
};
但根据你的情况,在设计上可能会有更好的解决方案。例如,如果 C
是输出的基础 class,而 A
是需要做一些日志记录的 class,您可以采用如下解决方案:
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);
现在 A
不关心输出到什么,只需要传递一个支持 Log
发送消息的 class 并让多态性处理其余的。事实上,如果你想要一个发送电子邮件的日志记录方法,只需创建一个 C
的新派生并将它传递到相同的 A
实例中。
您需要正确声明一个 B
数据成员,然后才能正确构造。
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) {}
};
我有 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;
};
最后(踢球者):从 "C" 派生的 class ,需要传递对 oss
的引用。
class D : public C{
public:
B b(&oss);
};
在行 B b(&oss);
我收到错误
error: expected identifier before ‘&’ token
老实说,我不知道我在这里是不是在玩火。基本思想是我希望 A 的一些函数写入一个公共输出流。
这不是日志记录 class 但我看到一些记录器声明了一个静态 oss 变量并允许每个人在那里写入。我宁愿避免这种情况,并在(逻辑上)正确的位置实例化我的 oss。就我而言,那是在 class C.
我认为(但我可能是错的)这里的错误是我试图通过 B b
的声明提供对变量 (oss) 的引用。那正确吗?相反,应该使用初始化列表来为构造函数提供值。但是我不确定如何实现它(并测试它是否编译)。
如果你想在 D
中有一个 B
类型的字段,你应该在那里声明它并在构造函数中初始化它,正如你已经暗示的那样:
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;
};
但根据你的情况,在设计上可能会有更好的解决方案。例如,如果 C
是输出的基础 class,而 A
是需要做一些日志记录的 class,您可以采用如下解决方案:
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);
现在 A
不关心输出到什么,只需要传递一个支持 Log
发送消息的 class 并让多态性处理其余的。事实上,如果你想要一个发送电子邮件的日志记录方法,只需创建一个 C
的新派生并将它传递到相同的 A
实例中。
您需要正确声明一个 B
数据成员,然后才能正确构造。
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) {}
};