【问题标题】:Can I force a compiler error if certain functions are not called?如果某些函数没有被调用,我可以强制编译错误吗?
【发布时间】:2012-06-28 20:35:43
【问题描述】:

this question 的启发,我想知道是否有任何技巧(如 SFINAE)来实现相反的效果。

编辑:添加示例

我有这样的东西(它非常简化,因为它有很多细节):

#include <iostream>

class Base {
public:
  Base(){}
  virtual ~Base(){
  }
  void initialize() { implementation(); }
private:
  virtual void implementation() = 0;
};

class Derived : public Base {
private:
  virtual void implementation() { std::cout << "initialization" << std::endl;}
};

int main() {

  std::unique_ptr<Base> b(new Derived());
  b->initialize();

  return 0;
}

初始化方法必须被调用。

但是如果我将初始化方法放在 Base 构造函数中,它将调用一个纯虚方法。 我想知道是否有办法防止有人不当使用构造的对象。

编辑:我的“解决方案”:

#include <iostream>

class Base {
public:
  virtual ~Base(){
  }
  Base() {};
private:
  void initialize() { implementation(); }
  virtual void implementation() = 0;
  template<class DerivedType> friend Base *factory();
};

class Derived : public Base {
private:
  Derived() {}
  virtual void implementation() { std::cout << "initialization" << std::endl;}
  template<class DerivedType> friend Base *factory();
};

template<class DerivedType>
static Base *factory(){
  Base *b = new DerivedType();
  b->initialize();
  return b;
}

int main() {

  std::unique_ptr<Base> b(factory<Derived>());

  return 0;
}

【问题讨论】:

  • 这有点投机/修辞。你有实际用例吗?
  • 有一些工具可以检测无法访问的代码。
  • 一般情况下不可能导致编译器错误。您只能通过运行程序来确定是否会调用函数。

标签: c++ visual-studio-2010 compiler-errors


【解决方案1】:

您不能强制编译器出错,但还有其他选择。

如果您的类型的实例根本无效,除非调用 initialize,并且如果记录该事实或在未初始化的情况下在使用时抛出异常是不可接受的,那么您应该将构造函数设为私有并公开一个静态方法来创建您的实例输入。

这样,您的代码客户端根本无法使用您的类型的未初始化实例。如果有更好、更优雅的方法我不知道(但也许这里有人知道)。

【讨论】:

  • 这就是我所做的,我的工厂类是我实例的朋友。
【解决方案2】:

请注意,这不应该是必需的,因为当您创建一个对象时,该对象可以正确初始化自身,而无需调用初始化函数。

这听起来可能很奇怪,但在大多数情况下initialization() 函数不正确:

class A
{
public:
    A() { do initialization of A fields here; }
};

class B : public A
{
public:
    B() { do initialization of B fields here; }
};

这在大多数情况下应该足够了。

如果您将参数传递给构造函数,您可能需要一些接口(不要在#include 中创建循环),然后您只需传递这些参数,如下所示:

class C;
class D;

class A
{
public:
    A(C c) { do initialization of A fields here; }
};

class B : public A
{
public:
    B(C c, D d) : A(c) { do initialization of B fields here; }
};

否则,为了在运行时进行验证,boost 和我的controlled_vars(使 int 等类型安全的模板,终于!)提供了检查字段是否已初始化的工具,它可以抛出并返回默认值价值。

否则我不知道编译器中有任何工具可以进行这样的测试。但是,如果您编写了一个测试(无论如何您都应该有测试!),那么您的测试可以进行此类验证。

请注意,我首先想到了探查器,但这需要一个测试,它无论如何都会告诉您您是否正确,探查器可以告诉您初始化已被调用,但您不知道这是否发生在所有情况。

但是,如 Ed S. 所述,要真正在编译时强制执行此类初始化(假设您确实需要它),最好的方法可能是使用工厂。这样所有丑陋的初始化代码都被隐藏了。

【讨论】:

  • 感谢您的回复。我不记得我需要这样的特定情况。我同意你的看法,所有初始化都必须在 ctor 或使用创建模式完成。
  • 是的。我正在开发一个从 .so 文件加载插件的系统。该初始化不能与 C++ 协同工作,因此我也有一些 init() 函数。然而在很多情况下,我们程序员做错了……我时常发现自己添加了一个无用的初始化函数!
猜你喜欢
  • 2012-05-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-07-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-02-11
相关资源
最近更新 更多