0

Consider this class:

class Downloader {
private:
        bool video_or_audio;
        // other variables [...]
        // [...]

        void downloadVideo(std::string videoURL);
        void downloadAudio(std::string audioURL);
public:
        void download();
}

Now, download() is defined this way:

void Downloader::download(){
        std::ifstream url_list;
        void (*download_func)(std::string) = video_or_audio == 0 ? downloadVideo : downloadAudio; // Compiler says here: "Reference to non static member function must be called".
  
        if(video_or_audio == 0){
                url_list.open("video_list.txt");
        }

        else{
                url_list.open("audio_list.txt");
        }

        std::string url;
        while(std::getline(url_list, url)){
                download_func(url); // Calling the function pointed by the pointer defined in line 2 of the function download().
        }

}

My compiler (clang) says: "Reference to non static member function must be called" in the second line of function download() definition. Why is this happening and how can I solve this problem?

A solution appears to be defining downloadVideo() and downloadAudio() functions to be static in the class declaration. However, if I do so, I cannot access private variables members of class Downloader, that's not desirable, as I need these variables.

Thank you!

Gabriel
  • 47
  • 4
  • Calling member functions by pointer takes a specific syntax that includes the object, it doesn't use `this` by default: `(object_ptr->*member_function_ptr)( params );`. So you need `(this->*download_func)(url)`. More detail in https://stackoverflow.com/questions/14814158/c-call-pointer-to-member-function – Aedoro Jun 08 '22 at 12:59
  • @Eljay, thank you for your comment. But, as I have written, "if I do so, I cannot access private variables members of class Downloader, that's not desirable, as I need these variables". – Gabriel Jun 08 '22 at 12:59
  • @Aedoro, thank you. This post seems to solve the problem. Yet, how can I implement it in my code? – Gabriel Jun 08 '22 at 13:03
  • @Gabriel i modified the comment – Aedoro Jun 08 '22 at 13:03
  • @Aedoro, I'm still having the same problem. My updated code is "void (*download_func)(std::string) = video_or_audio == 0 ? this->*downloadVideo : this->*downloadAudio;", it's where the compiler complains. The compiler does not complain about the line "download_func(url);", though. – Gabriel Jun 08 '22 at 13:12
  • `void (Downloader::*download_func)(std::string) = video_or_audio == 0 ? &Downloader::downloadVideo : &Downloader::downloadAudio;` seems to compile for me. Followed by: `(this->*download_func)(url);` – Borgleader Jun 08 '22 at 13:13
  • to avoid all that confusing pointer dereferencing when calling a member pointers you could use std::invoke. Makes it far more readable. – engf-010 Jun 08 '22 at 13:18

1 Answers1

0

Once calling a member function by pointer, you need to provide two things:

  • Member function itself

  • Address of particular instance of given class at which the member function to be called (because the function can access class members thus you have to advise which of the instances is the right one)

     void (Downloader::*download_func)(std::string) = video_or_audio == 0 ? &Downloader::downloadVideo : &Downloader::downloadAudio; // Correct the signatures.
     ...
     while(std::getline(url_list, url)){
         (this->*download_func)(url); 
     }
    

So, here we changed download_func from "just function pointer" to a member function pointer. Then, later in the loop body, we call this member function on this instance (however you can pass an instance as a param if necessary).

Yury Schkatula
  • 5,291
  • 2
  • 18
  • 42