2011-08-30 72 views
1

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

说我有

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 
     } 

} 

所以我应该能够只从方法onlyCallFooFromHere()

有没有办法实现这个叫A::foo?我愿意接受任何建议,包括更改班级设计。

编辑:

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

+4

为什么你需要那个?看起来像一个可怕的设计。你可以让'A'成员为私人并且使用友谊,但是友谊是全班级的,你不能只允许'myImpl'中的一个成员来调用它,而另一个成员不能。 –

+3

为什么你需要这样一个奇怪的类设计? – Nawaz

+0

这与设计朋友类一样糟糕......我只想将私有/受保护的方法限制为其他方法而不是类。我可以扩展为什么我需要这个,但是对于我正在寻找的答案,它没有任何区别...... –

回答

1

[免责声明:此解决方案将阻止墨菲,而不是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()方法。

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

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 */ } 
+0

这个解决方案是这样的:使用限定名'aspace :: A :: f()'来工作;和不合格的名称不起作用。 – Nawaz

+0

我从来没有声称这是漂亮的,或者说设计是有意义的:-) –

+0

另外,你可以*从你的外部雇佣团队身上扣下“Ah”文件(及其超级秘密的主要因素量子算法?)它实现'onlyCallFooFromHere()',如果你真的想...我的意思是,它仍然没有意义,但有时它是有趣的探索... –

3

更改一流的设计 - 你想要什么是不可能的。

我不确定你试图用这么一点细节来实现,我无法进一步发表评论。

+0

这将更适合作为评论。 –

+2

@Luchian:如果他认为你想要什么是不可能的,那么这是一个答案。 +1 – Nawaz

0

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

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

没有办法阻止特定的函数能够看到他们的范围内有什么可用(这是你问的),但是你可以设计你的基类,以便派生类只能访问特定的元素它。

这可能很有用,因为B类可以从类A继承为受保护的(从而获得它的受保护成员),而C类可以从公共类继承同一类A(因此不能访问其受保护的成员)。这可以让你至少获得某种形式的呼叫可用性差异 - 不同类别之间,而不是同一类别的功能之间。

+0

你的想法不起作用。如果'C'继承自'A',则它将能够访问'A'受保护的成员。 “C”是否公开地,受保护地或私下地从'A'继承只影响那些使用或从'C'派生的,而不是'C'本身的实现。 – Lambdageek

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中有什么原因吗?

相关问题