C ++ создает экземпляр шаблона функции в качестве члена класса и использует указатель this - PullRequest
3 голосов
/ 17 сентября 2010

У меня есть два класса (ClassA и ClassB), у каждого из которых есть два метода (сравнить и сходиться).Эти методы работают точно так же, но эти классы не связаны полиморфно (по уважительной причине).Я хотел бы определить шаблон функции, который оба эти класса могут явно создать в качестве члена, но я получаю ошибки, потому что методы используют «this», и когда я превращаю их в шаблон, компилятор выдает ошибку, потому что они нефункции-члены.

Разве это невозможно из-за этого ограничения?Или есть какой-то способ использовать «this» внутри шаблона функции, который не объявлен как часть класса шаблона.Я провел некоторые исследования и ничего не нашел.

Logic.h

template <class T>
T* compare(const T& t) {
//stuff involving this
}

template <class T>
T* converge(const T& t,bool b) {
//other stuff involving this
}

ClassA.cpp

#include "ClassA.h"
#include "Logic.h"
//constructors

template ClassA* ClassA::compare(const ClassA& t) const; 
template ClassA* ClassA::converge(const ClassA& t,bool b) const;
//other methods

classB похож.

Любая помощь приветствуется!

Ответы [ 3 ]

2 голосов
/ 17 сентября 2010

Я полагаю, что вы можете использовать CRTP здесь. Вот пример, вы можете опустить объявление friend, если вы можете выполнить сравнение, используя только открытые члены:

template<class T>
class comparer
{
public:
    T* compare(const T& t)
    {
        //Use this pointer
        bool  b =  static_cast<T*>(this)->m_b  == t.m_b;
        return NULL;
    }
};

class A : public comparer<A>
{
public:
    friend class comparer<A>;
    A() : m_b(0)
    {
    }

private:
    int m_b;
};

class B : public comparer<B>
{
public:
    friend class comparer<B>;
    B() : m_b(0)
    {
    }

private:
    int m_b;
};

int main()
{
    A a1,a2;
    A* p = a1.compare(a2);

    B b1,b2;
    B* p1 = b1.compare(b2);

    return 0;
}
0 голосов
/ 17 сентября 2010

То, что вы хотите, невозможно. Функции-члены должны быть объявлены и определены как члены. То же самое касается шаблонов функций-членов, из которых могут быть созданы экземпляры функций-членов.

Но (почему) эти функции должны быть членами? Если эти функции не нуждаются в доступе к личным вещам в этих классах, сделайте их бесплатными шаблонами функций. Весь STL (который, кстати, является лишь одной частью стандартной библиотеки C ++) построен на функциях, не являющихся членами, и достигает гораздо более высокого уровня абстракции, чем любая библиотека OO-контейнера, доступная раньше, чем когда-либо.
Вопреки распространенному мнению, функции, не являющиеся членами, обычно увеличение инкапсуляция :

Если вы пишете функцию, которая может быть реализована как член или не являющийся другом, не являющийся членом, вам следует предпочесть реализовать ее как функцию, не являющуюся членом. Это решение увеличивает инкапсуляцию класса. Когда вы думаете об инкапсуляции, вы должны думать о функциях, не являющихся членами.

0 голосов
/ 17 сентября 2010

Вы не можете использовать это внутри не-членской функции.Что вы можете сделать, это создать шаблонную функцию и объявить ее как друга ваших classA и classB.Но члены classA и classB, к которым обращается функция шаблона, должны иметь одинаковые имена.

template <typename T>
bool compare(const T& t1, const T& t2)
{
    return t1.val == t2.val;
}

class A
{
public:
    template <typename T>
    friend bool compare(const T&, const T&);

    bool compare(const A& a)
    {
        return ::compare(*this, a);
    }

private:
    int val;
};

A a1, a2;
a1.compare(a2);
...