about function calls from pointers to derived classes

Hello programmers!

I need your help to correctly call a function from a derived class, here the example:

I have such a header file with this virtual class:

1
2
3
4
5
6
7
8
#ifndef __FunzioneBase_h__
#define __FunzioneBase_h__

class FunzioneBase {
	public:
		virtual double Eval(double x) const =0;
		
};


which is linked to this derived class:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

class stepfunction: public FunzioneBase {

	public:

		stepfunction(double step, double intervallo); 
		~stepfunction();

		void SetN(int n) {_n = n;} //this value of n concerns the output of Eval virtual function

	
		virtual double Eval(double x) const;

	protected:

		double _step;
		double _intervallo;
		int _n;

};

#endif


Ok, no problem here.
What I'm struggling on is the correct syntax in order to call my void function SetN(int n) in this specific situation:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

int main() { //portion of main.cpp

	FunzioneBase* f = new stepfunction(1, 1);
	Integral* s = new Integral(-2, 2, f);


	double* c = new double[10];

	for(int n = 1; n <= 10; n++) {

		stepfunction->SetN(n); //HERE the problem. The compliator isn't that happy with such a call

		c[n] = (0.5)*s->simpson(100000); //simpson is an integration method from Integral class. It calls Eval virtual function in its body too.

	}



I actually get: " error: expected unqualified-id before '->' token".

I can't get it to work, I've tried several alternatives.
Can anyone point me out what I'm getting wrong? It would be really appreciated!

Thanks!


Last edited on
1. You have stepfunction->SetN(n); instead of f->SetN(n);

2. This wouldnt work anyway because f is of type FunzioneBase and so it doesnt have a SetN method
This is what you essentially do:
1
2
3
4
5
6
7
#include <string>

int main() {
	std::string foo("Hello");
	std::string* bar = &foo;
	std::string->size(); // error: expected unqualified-id before '->' token
}

Your stepfunction is a typename, just like the std::string.

You must call non-static member function with an object.

Remember that foo->bar is a shorthand for (*foo).bar, i.e. you have an object that you got via dereferencing a pointer.

1
2
3
4
5
6
7
#include <string>

int main() {
	std::string foo("Hello");
	std::string* bar = &foo;
	bar->size(); // ok
}


Would this work then?
1
2
FunzioneBase* f = new stepfunction(1, 1);
f->SetN(n);

No, for FunzioneBase does not have member SetN().

This is where dynamic_cast saves the day:
1
2
3
4
FunzioneBase* f = new stepfunction(1, 1);
if ( auto b = dynamic_cast<stepfunction*>(f) ) {
  b->SetN(n); // purrfect
}

Never heard about dynamic_cast conversion! What a wondeful way to work out this situation! I'll go to read more about that.
Thanks again!!

Have a nice programming you too
Last edited on
if you're iterating through a list of base classes, could add in a bit of logic to allow for a compile-time static_cast:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
#include <iostream>
#include <vector>
#include <string>

using namespace std;

class FunzioneBase {
public:
    virtual ~FunzioneBase() {}
    virtual bool IsStepFunction() { return false; }
    virtual string Name() { return "FunzioneBase"; }
};

class StepFunction: public FunzioneBase {

public:

    StepFunction(double step, double intervallo) :
        step_(step),
        intervallo_(intervallo)
    {        
    }
    ~StepFunction() {}

    void SetN(int n) {n_ = n;}

    bool IsStepFunction() override { return true; }
    string Name() override { return "StepFunction"; }

protected:

    double step_;
    double intervallo_;
    int n_;
};

int main() 
{
    FunzioneBase* f = new FunzioneBase();
    StepFunction* st = new StepFunction(1, 1);
    vector<FunzioneBase*> fpointers
    {
        f,
        st
    };
    
    for(int n = 1; n <= 3; n++) 
    {
        for (auto p : fpointers)
        {
            if (p->IsStepFunction())
            {
                cout << p->Name() << " is a step function\n";
                static_cast<StepFunction*>(p)->SetN(n);
            }
            else
            {
                cout << p->Name() << " is unfortunately not a step function\n";
            }
        }
    }

    delete f;
    delete st;

    return 0;
}


example running at https://repl.it/@icy_1/MellowThirstyDifference

You also want to define all the virtual non-pure functions.

Side note: I think it's C#'s thing, from the .NET team, to put prefix underscores in front of private vars, but in C++ vars starting with underscores are actually reserved (e.g. _WIN32) . I'd put underscores as suffixes if you like to use them.
Last edited on
side note: Win junk may use double underscore. I seem to remember having to type __stuff a lot. ?? Maybe they use a mix of the two formats?

thanks icy for the reply too, gave me lot to think about.

What if introducing dynamic_cast gave me compiler error: C++0x auto only available with -std=c++0x or -std=gnu++0x?


edit:

Ok, it concerned auto specifier. I solved substituting stepfunction* b to auto b
Last edited on
compiler error: C++0x auto only available with -std=c++0x or -std=gnu++0x

That tells that your compiler is GCC and a version that does have some C++11 features. The default language is C++03 with GNU extensions. The compiler option -std= can change that.

Current C++ is already C++17. You can most likely get a new version of GCC that has more up to date language support and you definitely should experiment with the -std=, for only the very latest versions of GCC do change the default from the (now ancient) C++03.

Furthermore, I'd recommend disabling the GNU extensions. They cause more confusion than benefit for a learner of C++.
Topic archived. No new replies allowed.