C++ 确保在编译时调用方法
如何确保在编译时调用特定的方法 例如,假设我有一个具有2种方法的对象:C++ 确保在编译时调用方法,c++,c++11,C++,C++11,如何确保在编译时调用特定的方法 例如,假设我有一个具有2种方法的对象: struct Foo { ... func1(...); ... func2(...); }; 我想确保在调用func2之前调用func1,即: int main() { Foo f; ... f.func1(...); f.func2(...); f.func2(...); // and so on } 但如果我这样做,我想生成一个编译错误: int main() { F
struct Foo
{
... func1(...);
... func2(...);
};
我想确保在调用func2之前调用func1,即:
int main()
{
Foo f;
...
f.func1(...);
f.func2(...);
f.func2(...); // and so on
}
但如果我这样做,我想生成一个编译错误:
int main()
{
Foo f;
...
f.func2(...); // generate a compile error due the fact that func1 must be called first
f.func1(...);
f.func2(...); // and so on
}
在编译时没有真正的方法来强制执行这一点。这是对象本身需要通过运行时检查强制执行的内容在编译时没有真正的方法强制执行。这是对象本身需要通过运行时检查强制执行的内容虽然您很好奇为什么要这样做,但一般注意的是,您必须向用户公开一个不能错误使用的界面。胆量私人化:
struct Foo
{
public:
void callme()
{
func1();
func2();
}
private:
... func1(...);
... func2(...);
};
int main()
{
Foo f;
f.callme();
}
如果需要强制执行对象的一次性初始化,请在构造函数中执行:
struct Foo
{
public:
Foo()
{
func1();
}
func2(...);
private:
... func1(...);
};
int main()
{
Foo f; // func1() called automagically
f.func2();
}
class Foo
{
private:
void func1(), func2();
friend class FooUser;
};
class FooUser
{
public:
explicit Proxy(FooUser& f) : f_(f) {
f.func1();
}
void func2() {
f_.func2();
}
};
在设计类接口时,您必须始终考虑最糟糕的事情:用户从不阅读文档,用户总是忘记调用
foo.initialize()
,用户总是忘记释放内存和内存泄漏,等等,一般注意事项是,您必须向用户公开一个不能错误使用的界面。胆量私人化:
struct Foo
{
public:
void callme()
{
func1();
func2();
}
private:
... func1(...);
... func2(...);
};
int main()
{
Foo f;
f.callme();
}
如果需要强制执行对象的一次性初始化,请在构造函数中执行:
struct Foo
{
public:
Foo()
{
func1();
}
func2(...);
private:
... func1(...);
};
int main()
{
Foo f; // func1() called automagically
f.func2();
}
class Foo
{
private:
void func1(), func2();
friend class FooUser;
};
class FooUser
{
public:
explicit Proxy(FooUser& f) : f_(f) {
f.func1();
}
void func2() {
f_.func2();
}
};
在设计类接口时,您必须始终考虑最糟糕的事情:用户从不阅读文档,用户总是忘记调用
foo.initialize()
,用户总是忘记释放内存和内存泄漏,等等。想到的一种方法是让func1()返回一个对象,该对象充当func2()的代理:
另一种方法(也是我最喜欢的方法)是让func1()成为构造函数,或者使用另一个类,该类在其构造函数中调用func1():
struct Foo
{
public:
Foo()
{
func1();
}
func2(...);
private:
... func1(...);
};
int main()
{
Foo f; // func1() called automagically
f.func2();
}
class Foo
{
private:
void func1(), func2();
friend class FooUser;
};
class FooUser
{
public:
explicit Proxy(FooUser& f) : f_(f) {
f.func1();
}
void func2() {
f_.func2();
}
};
我想到的一种方法是让func1()返回一个对象,该对象的行为类似于func2()的代理: 另一种方法(也是我最喜欢的方法)是让func1()成为构造函数,或者使用另一个类,该类在其构造函数中调用func1():
struct Foo
{
public:
Foo()
{
func1();
}
func2(...);
private:
... func1(...);
};
int main()
{
Foo f; // func1() called automagically
f.func2();
}
class Foo
{
private:
void func1(), func2();
friend class FooUser;
};
class FooUser
{
public:
explicit Proxy(FooUser& f) : f_(f) {
f.func1();
}
void func2() {
f_.func2();
}
};
编译器不能强制执行函数调用的顺序,因为通常只能在运行时确定。但它可以在使用对象之前强制对象初始化。因此,获得编译时检查的最佳方法是执行
func1
在构造函数中所做的任何操作-要么是Foo
的构造函数的一部分,要么是为了调用func2
而需要创建的帮助对象,编译器无法强制执行函数调用的顺序,因为通常只能在运行时确定。但它可以在使用对象之前强制对象初始化。因此,获得编译时检查的最佳方法是执行func1
在构造函数中所做的任何操作-要么是Foo
的构造函数的一部分,要么是为了调用func2
而需要创建的帮助对象,我确实不建议这样做,但如果出于调试目的需要它,您可以尝试以下操作。
将每个调用func1()更改为
和func2()到
因此,如果在文本的上面提到func2(),然后是func1,则会收到编译时错误。这并不意味着它将在执行过程中被提前调用。我确实不建议这样做,但如果您出于调试目的需要它,您可以尝试以下操作。 将每个调用func1()更改为 和func2()到
因此,如果在文本的上面提到func2(),然后是func1,则会收到编译时错误。这并不意味着它将在执行过程中被提前调用。您可以尝试使用
constepr
,但在这种情况下它不会工作。(不保证在任何情况下都能工作)。我想这只能通过代码分析器来完成。编译器本身只能警告您一个未使用的函数-AFAIK。如果您需要这样做,您可能应该继续考虑更好的类设计。这是一个压缩耦合反模式:您可以尝试使用constexpr
,但在这种情况下它不会工作。(不保证在任何情况下都能工作)。我想这只能通过代码分析器来完成。编译器本身只能警告您一个未使用的函数-AFAIK。如果您需要这样做,您可能应该继续考虑更好的类设计。这是一个纯粹的耦合反模式:我还要提到,您可以使用std::forward
将参数从callme
传递到func1…funcn
。只要有足够的决心,你就可以从它应该使用的函数列表中自动创建callme
的签名,使其更加透明。你问过我为什么要这样做。看看这篇文章()。在这里,当您使用模板执行策略模式(不确定它是否真的是一个策略模式)时,您初始化对象,而不是通过构造函数,而是调用init函数。我想确保用户已经这样做了,但是在编译时。@TomásBadan我认为在本例中,init()
方法没有任何必要。事实上,它们可以被构造函数替换。因此,无论以前在哪里和谁调用init()
,现在都只需将参数传递给构造函数或工厂(工厂将参数传递给构造函数)。@Drop如文中所述:“(…)writer类实现了…init方法…来初始化对象…因为我们将它们定义为记录器的基类,而这个类不能拥有所有可能的超类的“构造函数”。(…)。因此,即使将init参数传递给基构造函数,问题是,用户必须调用init来初始化基对象,否则,它们很可能由默认构造函数初始化。@TomásBadan我们确实可以在基类中使用任何参数组合的构造函数(可变模板魔术)。还有其他解决办法。顺便说一下,本文中描述的模式与“策略”没有任何共同之处。它被称为。但是这个问题