考虑以下两个类:
class Parent
{
private:
char outputBuffer[100];
protected:
virtual void WriteOutput() = 0;
};
class Child : public Parent
{
private:
double value1;
double value2;
void WriteOutput()
{
sprintf(outputBuffer, "%.2f %.2f", value1, value2);
}
};
父级定义一个virtual
函数,然后在子级中实现,其目的是将格式化的字符串写入输出缓冲区。
我的挑战是我希望输出缓冲区不能直接对子类可见。换句话说,我希望WriteOutput看起来像:
void WriteOutput()
{
myFcn("%.2f %.2f", value1, value2);
}
但是myFcn()
看起来像什么?它应该只是转发到sprintf,但支持sprintf中的varags所需的语法让我感到困惑。是否可以传递可变数量的参数?我在示例中显示了两个值,但不同的子项将具有不同数量的值,因此我必须保留sprintf的vararg功能。请注意,性能在这里很重要,所以我不能有不必要的字符串副本。
如果在这种情况下有一个更好/更有效的sprintf替代方案,我可以考虑一下。感谢。
答案 0 :(得分:3)
在Sutter and Alexandrescu's C++ Coding Standards中,您可以找到以下项目:
- 考虑将虚拟功能设为非公共功能,将公共功能设置为非虚拟功能。 68
醇>
我相信,即使你的问题没有特别涉及公共/私人方面,其理由也在这里。非virtual
方法应该说"外部" 它的作用,virtual
方法应该说 它是如何做到的。
因此,他们不需要具有相同的签名。事实上,这是怎么回事:
class Parent
{
private:
char outputBuffer[100];
protected:
virtual void WriteOutputImp(char outputBuffer[100]) = 0;
public:
void WriteOutput()
{
WriteOutputImp(outputBuffer);
}
};
class Child : public Parent
{
private:
double value1;
double value2;
protected:
virtual void WriteOutputImp(char outputBuffer[100])
{
sprintf(outputBuffer, "%.2f %.2f", value1, value2);
}
};
编辑正确地提及@ 5gon12eder(恕我直言),当您正在使用它时,您可以考虑将char ...[100]
更改为更安全的内容。这完全正确,但是另外一点。
答案 1 :(得分:0)
您可以使用新的可变参数模板。即。
#include <iostream>
#include <iomanip>
void write()
{ }
template<typename... Params>
void write(double toPrint, Params... args)
{
std::string str = "%.2f";
const int size = sizeof...(args);
if(size > 0U)
str += " ";
sprintf(outputBuffer, str.c_str(), toPrint);
write(args...);
}
您可以通过WriteOutput
这样的write(5.1, 1.23, mydoublevalue, 9.993)
个人方法拨打此电话。
但是,您可能希望最小化sprintf
次呼叫,并采用其他方法:
template<typename... Params>
std::string construct()
{ return std::string(); }
template<typename... Params>
std::string construct(double toPrint, Params... args)
{
std::string str = "%.2f";
const int size = sizeof...(args);
if(size > 0U)
str += " ";
str += construct(args...);
return str;
}
template<typename... Params>
void write(Params... args)
{
sprintf(outputBuffer, (construct(args...)).c_str(), args...);
}
通话相同,但只使用一次sprintf
通话。看到它正常工作online!