Tablica wskazników na metody

0

Cześć,
Próbuję zrozumieć istotę wskaźników na metody, żeby zrobić zadanie na studia.
Mamy przykładowo plik
A.h

class A {
    private:
        const int static = 3;
    public:
        A();
        double f1() const { return 1; }
        double f2() const { return 2; }
        double f3() const { return 3; }
        
}

Potrzebuję utworzyć tablicę wskaźników na te trzy metody, a następnie w konstruktorach kolejno przypisać do tej tablicy funkcje f1,f2,f3. Niestety nie mam pojęcia jak w ogóle zdeklarować taką tablicę wskaźników na metody[wskaźniki na funkcje rozumiem] oraz jak ją później wypełnić. Dodatkowym utrudnieniem jest fakt, że nie mogę skorzystać z vector oraz array, musi to być na zwykłych wskaźnikach.

Jakieś porady?

E: tablica ma być składową publiczną klasy, a wypełnienia ma nastąpić w konstruktorze w pliku .cpp

3

Na zachętę masz tutaj przykład z std::string:

int main(){
    size_t (string::*foo[3])() const = { &string::size, &string::size, &string::size };
}

Ale zdecydowanie polecam zrobić sobie kilka aliasów dla czytelności, bo to jest kompletnie nieczytelne. https://dev.krzaq.cc/post/readable-function-pointers/

0

Dzięki, będę próbował.

Obawiam się, że aliasy wykraczają poza poziom zrozumienia mojego ćwiczeniowca i tłumaczenie wszystkiego mogłoby okazać się trudne. :v

0

zdeklarowałem sobie to tak:

double (A::*ptr_fun[_size])() const;

natomiast w konstruktorze:

ptr_fun[0] = &A::fun1;
    ptr_fun[1] = &A::fun2;
    ptr_fun[2] = &A::fun3;

Stworzyłem klasę B:

class B 
{
    private:
        static const int size = 4;
        A a[size];
    public:
        A();
        A operator[](int i) { return a[i]; }
        
}

W konstruktorze klasy B, tworzę 4 obiekty, przypisane do tablicy

for(auto i = 0; i < size; i++)
     a[i] = A();

W metodzie display(const B& b), która należy do klasy B, próbuję wyświetlać wywołanie tablicy wskaźników do funkcji dla tablicy a z klasy B, robię to w ten sposób(metoda jest zaprzyjaźniona, powód tego mam, tutaj chce zobrazować dokładnie problem):

for(auto i = 0; i < 4; i++)
    for(auto ii = 0; i < 3; i++)
         std::cout << b[i].ptr_fun[ii]  << "\n";

Niestety nie działa to tak jak powinno[to jest 4 krotne wypisanie 1,2,3]. Gdzie popełniam błąd?

1

Wywołanie wskaźnika na metodę jest również "mega proste". Albo std::invoke (C++17), albo (A{}.*arr[0])() - inaczej mówiąc (objekt.*ptr)(params...) lub (ptr_obj->*ptr_fun)(params...)

0

Hmm, gdy próbuje to robić w ten sposób dostaje, że ptr_fun jest niezdeklarowane :V
a robie to zgodnie z tym co podałeś (obiekt[i].ptr[ii])()

0

A gwiazdka gdzie?

0

Z gwiazdką przed ptr_fun dalej "was not declared in this scope

0

ptr_fun[ii] weź w nawiasy, bo źle binduje.


struct A
{
        static const int arr_size = 3;
        double f1() const { return 1; }
        double f2() const { return 2; }
        double f3() const { return 3; }

};

int main ()
{
    double (A::*ptr_fun[A::arr_size])() const = {
        &A::f1, &A::f2, &A::f3
    };

    A a;
    for(int i = 0; i < A::arr_size; i++){
        auto result = (a.*(ptr_fun[i]))();
        DBG(result);
    }
}

https://wandbox.org/permlink/UYIJpEQ7Nn1iYfxn

Przy okazji, zobacz o ile czytelniejsza jest wersja z invoke:

    for(int i = 0; i < A::arr_size; i++){
//        auto result = (a.*(ptr_fun[i]))();
        auto result = invoke(ptr_fun[i], a);
        DBG(result);
    }

https://wandbox.org/permlink/Z9iIiHBrZ8dMLKJV

0

Dalej rzuca tym samym, was not declared[...]. Może błąd jest gdzieś indziej?

0

Pokaż kod.

0

complex.h

#ifndef COMPLEX_H
#define COMPLEX_H

#include <math.h>

class Complex
{
private:
    static const int _size = 4;

    double _re;
    double _im;

public:
    Complex();
    Complex(double re);
    Complex(double re, double im);

    double getRe() const { return _re;}
    double getIm() const { return _im; }

    double getSumSquared() const { return (_re * _re) + (_im * _im); }
    double getSquareRoot() const { return sqrt(getSumSquared());}

    double (Complex::*ptr_fun[_size])() const;

};

complex.cpp

#include "complex.h"


Complex::Complex() : _re(0.0), _im(0.0) {
    ptr_fun[0] = &Complex::getRe;
    ptr_fun[1] = &Complex::getIm;
    ptr_fun[2] = &Complex::getSumSquared;
    ptr_fun[3] = &Complex::getSquareRoot;
}

Complex::Complex(double re) : _re(re), _im(0.0) {
    ptr_fun[0] = &Complex::getRe;
    ptr_fun[1] = &Complex::getIm;
    ptr_fun[2] = &Complex::getSumSquared;
    ptr_fun[3] = &Complex::getSquareRoot;
}

Complex::Complex(double re, double im) : _re(re), _im(im) {
    ptr_fun[0] = &Complex::getRe;
    ptr_fun[1] = &Complex::getIm;
    ptr_fun[2] = &Complex::getSumSquared;
    ptr_fun[3] = &Complex::getSquareRoot;
}

arr_complex.h

#ifndef ARR_COMPLEX_H
#define ARR_COMPLEX_H

#include <complex.h>
#include <iostream>

using std::ostream;

class Arr_complex
{
private:
    static const int _size = 10;
    Complex arr_c[_size];
public:
    Arr_complex();
    friend ostream & operator <<(ostream& os, const Arr_complex ac);
    Complex& operator[](int i);
};

arr_complex.cpp

#include "arr_complex.h"

Arr_complex::Arr_complex()
{
    for(auto i = 0; i < _size; i++) {
        arr_c[i] = Complex(i, i);
    }
}

Complex& Arr_complex::operator [](int i)
{
    return arr_c[i];
}

ostream& operator <<(ostream& os, Arr_complex ar)
{
    for(auto i = 0; i < 10; i++)
        for(auto ii = 0; ii < 4; ii++)
            auto result = (ar[i].*(ptr_fun[ii]))();
            os << result << "\n";
    return os;
}
0

Szkoda, że nie podałeś błędu. Na oko

    for(auto i = 0; i < 10; i++)
        for(auto ii = 0; ii < 4; ii++)
            auto result = (ar[i].*(ptr_fun[ii]))();
            os << result << "\n";

Nie chciało ci sie wstawiać klamerek, to nie python, indentacja nie ma znaczenia.

    for(auto i = 0; i < 10; i++)
        for(auto ii = 0; ii < 4; ii++)
            auto result = (ar[i].*(ptr_fun[ii]))();



    os << result << "\n";
0

Brak klamer przez pośpiech, po ich dodaniu dalej to samo co wcześniej czyli ptr_fun was not declared in this scope

1

Wcześniej podałeś tylko część komunikatu błędu, myślałem, że chodzi o result not in scope. Polecam podawanie całego komunikatu błędu.

auto result = (ar[i].*(ar[i].ptr_fun[ii]))();

Chociaż trzymanie identycznej tablicy jako non-static membera każdej instancji wydaje się zbędne.

0

Dziękuję, działa.

Co do zbędności, robię te zadania, żeby je zrobić i po 5 minutach zajęć iść na obiad. C++ staram się uczyć w nowym wydaniu.

1 użytkowników online, w tym zalogowanych: 0, gości: 1