2016-05-11 4 views
2

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

Мой вопрос: есть ли способ объявить функцию с неизвестным именем (т. Е. Только тип возвращаемого значения и набор аргументов известен) как друга? Я хочу это, потому что в будущей разработке могут быть добавлены новые функции, а класс остается тем же, и я не хочу добавлять новое объявление для каждой новой функции.

Конечно, я также открыт для других подходов к достижению моей цели.

#include <iostream> 

class foo 
{ 
private: 
    int var_1; 
public: 
    foo(void (*functionPtr)(foo*)) 
    { 
     functionPtr(this); 
    } 
    ~foo(){} 

    int get_var() {return var_1;} 

    friend void function_1(foo*); // declare all unique 
    friend void function_2(foo*); // functions as friends 

    /*friend void (*functionPtr)(foo*); // this is what I want: 
             // to declare all functions with 
             // a specific return type and 
             // specific arguments as a friend 
             // of this class */ 
}; 

void function_1(foo* T) 
{ 
    std::cout << "function 1" << std::endl; 
    T->var_1 = 1; 
} 

void function_2(foo* T) 
{ 
    std::cout << "function 2" << std::endl; 
    T->var_1 = 2; 
} 

int main() 
{ 
    foo F1(&function_1); 
    std::cout << F1.get_var() << std::endl; 

    foo F2(&function_2); 
    std::cout << F2.get_var() << std::endl; 

    return 0; 
} 
+1

Я слишком стар и ржавый, чтобы рассмотреть это в деталях, но изучать * посетителя * рисунок. – Bathsheba

+0

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

+1

Как Вирсавия заметила, что вы можете принять образец для этого. Я бы рекомендовал посмотреть на заводскую модель. – teivaz

ответ

1

Вы можете перемещать части, которые вы хотите, чтобы инициализировать в отдельное место, где они считаются общественности:

struct foovars 
{ 
    int var_1; 
}; 

class foo : foovars 
{ 
public: 
    foo(void (*functionPtr)(foovars*)) 
    { 
     functionPtr(this); 
    } 
}; 

void function_1(foovars* T) 
{ 
    std::cout << "function 1" << std::endl; 
    T->var_1 = 1; 
} 

Теперь ваша переменная член как частный, как это было раньше, с точки зрения код, содержащий экземпляр class foo. Но специальные функции, которые могут получить foovars*, могут изменять своих членов.

+0

Это делает именно то, что я пытаюсь сделать, спасибо: D – Sjonnie

+0

@Sjonnie: Добро пожаловать. Если этот ответ решает вашу проблему, подумайте о том, чтобы «принять» его, нажав галочку слева. –

+0

Если переменные имеют открытый интерфейс, почему мы просто не инкапсулируем их и не передаем их с использованием семантики копирования? Это будет более четким и эффективным. –

0

Статические class функции будут работать лучше здесь:

class foo 
{ 
private: 
    int var_1; 
public: 
    foo(void (*functionPtr)(foo*)) 
    { 
     functionPtr(this); 
    } 
    ~foo(){} 

    int get_var() {return var_1;} 

    static void function_1(foo*); // declare all unique 
    static void function_2(foo*); // functions as friends 

}; 

void foo::function_1(foo* T) 
{ 
    std::cout << "function 1" << std::endl; 
    T->var_1 = 1; 
} 

void foo::function_2(foo* T) 
{ 
    std::cout << "function 2" << std::endl; 
    T->var_1 = 2; 
} 


int main() 
{ 
    foo F1(&foo::function_1); 
    std::cout << F1.get_var() << std::endl; 

    foo F2(&foo:function_2); 
    std::cout << F2.get_var() << std::endl; 

    return 0; 
} 

Поскольку они являются членами класса, не friend не требуется, и они имеют полный доступ к private членов класса.

Еще лучше, функции static могут быть private и недоступны вне класса.

+0

Это требует модификации определения класса каждый раз, когда вы хотите добавить новую функцию. То, как я интерпретировало этот вопрос, было неприемлемым, иначе подход «друг» будет работать. –

+0

Вы не должны поощрять этот ужасный анти-шаблон. Вы будете нести ответственность за следующее поколение кода мусора. –

+0

Как сказал Джон, это действительно добавляет больше к классу, который я хочу оставить неизменным. – Sjonnie

0

В этом случае используйте отправку тегов. Он (много) более удобен в обслуживании и приведет к более эффективному коду.

#include <iostream> 

class foo 
{ 
private: 
    int var_1; 
public: 
    struct type1_type {}; static constexpr type1_type type1{}; 
    struct type2_type {}; static constexpr type2_type type2{}; 

    foo(type1_type) 
    : var_1(1) 
    { 
     // initialisation for type 1 construction 
    } 

    foo(type2_type) 
    : var_1(2) 
    { 
     // initialisation for type 2 construction 
    } 

    ~foo(){} 

    int get_var() {return var_1;} 


}; 

int main() 
{ 
    foo F1(foo::type1); 
    std::cout << F1.get_var() << std::endl; 

    foo F2(foo::type2); 
    std::cout << F2.get_var() << std::endl; 

    return 0; 
} 

ожидаемый результат:

1 
2 
+0

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

Смежные вопросы