限制方法调用另一个方法

时间:2011-08-30 19:04:44

标签: c++ oop design-patterns

对此可能有一个相当简单和直接的答案,但由于某种原因我无法看到它。 我需要将类中的调用方法限制为某些接口的派生类实现的某些方法。

说我有

class A{
    public:
        static void foo();
};

class myInterface{
    public:
        virtual void onlyCallFooFromHere() = 0;
}

class myImplementation : public myInterface{
    public:
        virtual void onlyCallFooFromHere()
        {
            A::foo(); //this should work
        }
        void otherFoo()
        {
            A::foo(); //i want to get a compilation error here
        }

}

所以我应该只能从A::foo

方法拨打onlyCallFooFromHere()

有没有办法实现这个目标?我愿意接受任何建议,包括改变班级设计。

编辑:

所以......我觉得有必要进一步解释这个问题。我有一个与数据库交互的实用程序类(主要是更新记录) - 类A. 在我的界面(代表一个基本的数据库对象)中,我有虚函数updateRecord(),我可以从db实用程序类调用方法。我想强制只在所有扩展类的updateRecord()函数中更新数据库,而不是其他任何地方。即使不可能,我也不认为这是一个糟糕的设计选择。但是,如果确实不可能,我将不胜感激。

5 个答案:

答案 0 :(得分:3)

改变班级设计 - 你想要的是不可能的。

我不确定你想用这么少的细节来实现什么,我无法进一步评论。

答案 1 :(得分:1)

[免责声明:此解决方案将阻止Murphy,而不是Macchiavelli。]

怎么样:

class DatabaseQueryInterface {
public:
  ~virtual DatabseQueryInterface() = 0;
  virtual Query compileQuery() const = 0; // or whatever
  virtual ResultSet runQuery(const Query&) const = 0; // etc
};

class DatabaseUpdateInterface : public DatabaseQueryInterface {
public:
   virtual Update compileUpdate() const = 0; // whatever
};

class DatabaseObject {
public:
  virtual ~DatabaseObject() = 0;
protected:
  virtual void queryRecord(const DatabaseQueryInterface& interface) = 0;
  virtual void updateRecord(const DatabaseUpdateInterface& interface) = 0;
};

class SomeConcreteDatabaseObject : public DatabaseObject {
  protected:
     virtual void updateRecord(const DatabaseUpdateInterface& interface) {
        // gets to use interface->compileUpdate()
     }

     virtual void queryRecord(const DatabaseQueryInterface& interface) {
        // only gets query methods, no updates
     }
};

所以基本的想法是你的DatabaseObject基类松开私有的Query对象和私有的Update对象,当需要调用子类的受保护成员时取消Update方法的updateRecord()界面和Query方法的queryRecord()界面。

这样,子类的自然之处在于使用它们传递的对象与数据库进行通信。当然,他们总是可以使用肮脏的技巧来存储传入的Update对象并尝试稍后从查询方法中使用它,但坦率地说,如果它们达到这样的长度,它们就是自己的。 / p>

答案 2 :(得分:0)

您可以将项目拆分为不同的TU:

// A.h
class A
{
public:
    static void foo();
};


// My.h
class myInterface
{
public:
    virtual void onlyCallFooFromHere() = 0;
}

class myImplementation : public myInterface
{
public:
    virtual void onlyCallFooFromHere();
    void otherFoo();
};


// My-with-A.cpp
#include "My.h"
#include "A.h"

void myImplementation::onlyCallFooFromHere() { /* use A */ }


// My-without-A.cpp
#include "My.h"

void myImplementation::otherFoo() { /* no A here */ }

答案 3 :(得分:0)

您可能知道这一点,但通过继承,您可以拥有公共,受保护和私有成员访问权限。

如果一个成员在基类中是私有的,派生者就无法访问它,而如果同一个成员受到保护,那么派生类可以访问它(虽然它仍然不是公共的,所以你要保持封装)

没有办法阻止特定函数在其范围内看到可用的内容(这就是您要问的内容),但您可以设计基类,以便派生类只能访问它的特定元素

这可能很有用,因为B类可以从A类继承为受保护(因此获得其受保护的成员),而C类可以从同一个A类继承为public(因此无法访问其受保护的成员)。这将使您至少在某些类之间获得某种形式的调用可用性差异 - 但不是在同一类中的函数之间。

答案 4 :(得分:0)

这可行。

class myInterface;

class A {
    private:
        friend class myInterface;
        static void foo();
};

class myInterface {
    public:
        virtual void onlyCallFooFromHere() {callFoo();}
    protected:
        void callFoo() {A::foo();}
};

虽然在这一点上我认为我只是让A :: foo成为myInterface的静态。这些问题不再是真正分开的了。

class myInterface {
    protected:
        static void foo();
};

foo是否有原因在A?