abstract methods, virtual methods

Pages: 123
What I have tried

1
2
3
4
5
6
7
Condition& source; // not initiated - produces error
Effect& source_; // not initiated
// I cannot initiate the source and source_ because I don't know the type yet
if (data->type == EFFECT)
	std::swap(source, source_);
source = t->conds[data->index];
source.tobuffer(nullbuff);
Last edited on
Hi h4ever,

What you're trying to do is creating reference to nothing. When you write

Condition& source;
or
Effect& source_;

You are trying to build reference, that is alias to something, without this "something" that you MUST provide.

What you would need to do instead is playing with pointers, not references. Like this:

Condition *source;
Effect* source_;

Because pointers can be declared without being initialised, unlike reference.
But it seems that std:swap does not accept pointers*.
Last edited on
If I'm not wrong, from the prototype of std::swap:

template <class T> void swap (T& a, T& b);

when you will call
Conditions* source;
Effect* source_;
std::swap(source, source_);

You will pass pointers by reference, which is fine. The prototype simply says that whatever you give to the function, it is passed by reference. So you can give it pointers, they will be passed by reference.

This is my understanding but I'm not sure.

However, since your pointers don't point to anything at this level, I'm not sure why you want to do that.
I tried it before and it cannot work. It is type mismash. pointer * is not the same type as &.

It results in error
trigedit.cpp(894): error C2784: 'void std::swap(_Ty (&)[_Size],_Ty (&)[_Size])' : could not deduce template argument for '_Ty (&)[_Size]' from 'Condition *'
visual studio 10.0\vc\include\algorithm(1029) : see declaration of 'std::swap'
trigedit.cpp(894): error C2784: 'void std::swap(std::_Vb_reference<_Alloc>,std::_Vb_reference<_Alloc>)' : could not deduce template argument for 'std::_Vb_reference<_Alloc>' from 'Condition *'
visual studio 10.0\vc\include\vector(1659) : see declaration of 'std::swap'

I think that it means that it expects pointer type &.
The variable is declared as dereference operator
http://en.wikipedia.org/wiki/Dereference_operator
http://stackoverflow.com/questions/596636/c-difference-between-ampersand-and-asterisk-in-function-method-declar
I think the & is used because the Effect and Condition classes include methods. But I need to swap them too (the swap uses pointer type &).

Also to explain why... I have two types (instances of two classes) which have similar data, but they are used for different purposes. There is a method which accepts data related to Conditions or related to Effects. And I want to create pointer "source" which will pointer type Condition or to pointer type Effects. The pointer should point to buffer keeping this data.
Last edited on
Hi again, I'm quite sure about what I said (but I can be wrong) and I made a simple test:
1
2
3
4
5
6
7
8
9
10
#include <iostream>

int main(){

    int *p1;
    int *p2;
    std::swap(p1, p2);

    return 0;
}


That compiles an run perfectly.

Now I notice that you're swapping two different things. If you use pointers, you have on one side a pointer to Conditions and on the other side, a pointer to Effect. You cannot swap two different types, and this is seen in the prototype of std::swap
that requires two arguments of the same type, passed by reference.

Or maybe swap wants template argument. But which argument to enter then? The sources are both different types.

basically, all I want to do is something like this:

1
2
3
4
if (data->type == EFFECT) // @@@
	source& = t->effects[data->index];
if (data->type == CONDITION) // @@@
	source& = t->conds[data->index];


but problem is that source is not declared. For the declaration I need something like this
1
2
3
4
if (data->type == EFFECT) // @@@
	Effect source& = t->effects[data->index];
if (data->type == CONDITION) // @@@
	Condition source& = t->conds[data->index];

but this does not work correctly
Last edited on
If Condition and Effect are two independent classes, then you cannot do what you want since it is not allowed (because it doesn't make sens).
If you say that they have some common stuff, then you can try to create a mother class from which Condition and Effect would be daughter classes.

Then you would be able to do something like this:

MotherClass *source;

if(data->type == Effect) {
source = new Effect();
}
else {
source = new Condition();
}

But this requires to stop for couple hours, and think about the design of these classes, see if it is really necessary, etc...

But I think I'm not understanding exactly what you want to do. The above code is what we do when we don't know a priori the exact class will be used: Condition or Effect.
I tried to find out if it is possible to use some solution without need to add them to mother class.

E.g. I tried this

if (data->type == EFFECT)
Effect& source = t->effects[data->index];
if (data->type == CONDITION) // @@@
Condition& source = t->conds[data->index];
source.tobuffer(nullbuff); // error undeclared identifier 'source' :-(

Well, I will go back to mother class and have the methods to be declared in mother class. The thing I wanted to do originally is to avoid virtual methods. And now I realized (I hope that I am not wrong) that I don't need virtual methods because the methods which are under Condition and under Effect have same name, but they are defined in different classed so they don't need to be virtual.
As a last word, you could also make a single class that would handle both the effect and the condition.

It's not really C++ oriented solution but if your code is small... it could do it.

Good luck ;)
I did go back to original project but I try to remove virtual/abstract methods and make them normal methods. But I got this error:

trigedit.obj : error LNK2019: unresolved external symbol "public: void __thiscall ECBase::tobuffer(class Buffer &)const " (?tobuffer@ECBase@@QBEXAAVBuffer@@@Z) referenced in function "void __cdecl Trig_ToClipboard(struct HWND__ *,class Trigger *,class ItemData *)" (?Trig_ToClipboard@@YAXPAUHWND__@@PAVTrigger@@PAVItemData@@@Z)
.\aokts.exe : fatal error LNK1120: 1 unresolved externals


Do you know how to solve the external ?
I dont see any library pointed to mother class

Related Trigger implementation
1
2
Trigger::Trigger(Buffer& buffer)
void Trigger::tobuffer(Buffer& buffer) const


Is it because the Trigger class in not inherited from ECBase?
Last edited on
That is a linker error.

A function calls void ECBase::tobuffer(Buffer &) const. Compiler has compiled the function, so the function has been declared in the scope. However, no object file (including the libraries) that is included in the linking stage does contain the implementation for the function.

Simpler example:
1
2
3
4
5
6
7
void foo();

int main()
{
  foo();
  return 0;
}

That file will compile, but the resulting object file cannot be linked to become an executable. Not without an object file that provides this:

1
2
3
4
void foo()
{
  // ...
}
This is the function:
http://paste.ofcode.org/9H2eAjRYTdHjyg8CHTWyMv
calls:
t->tobuffer(nullbuff);
and
t->tobuffer(MemBuffer(clip_buff, needed));

And here is the definition to Trigger class:
Edit: (sorry this is Trigger constructor)
http://paste.ofcode.org/3ayRCHgYa7qmaDYBVwmFgQ

and the Trigger method toBuffer:
http://paste.ofcode.org/SpHTxzqEZphsvvTu8QZf2r

The Trigger class does not inherit from ECBase. So this is confusing, how could it call ECBase's method?
Last edited on
... here is the definition to Trigger class ...

No, there is not. What you link is code for a constructor.
Then this is the Trigger code (declaration):
http://paste.ofcode.org/9jPGyCsLqgHXrfxWUCX8Rz
You have:
1
2
3
ECBase& source = ...

source.tobuffer(nullbuff);
Well, there is line in mother class ECBase:
virtual void tobuffer(Buffer &b) const = 0;
with this lines it works fine. This does not print any error! But I thought that the abstract class is not needed. So I changed it to
void tobuffer(Buffer &b) const;
Can you explain why it was not error when using abstract/virtual class?
Last edited on
Can you explain what is/does a virtual function?
Can you explain what is a pure virtual function?

Let Foo be an abstract class. Can one or can't one do:
Foo bar;
I do not understand to the pure virtual function. * - OK, I've found answer: "A pure virtual function or pure virtual method is a virtual function that is required to be implemented by a derived class that is not abstract" - Wikipedia. So virtual function in general - needs not to be derived? For example when creating class template...?

A virtual keyword as I understand it - when you need to use some member in declaration or definition of some code like template but the value is unknown at the moment or it was not initiated yet. So it can be method or variable in a class. Using virtual means that the decision which method will be called is made during call of program, not in compilation. Also, now I read back: difference between earlier build and later build is at the normal function, there is a check if the method is really called on proper object. It could be the key problem. So when I use virtual keyword so it does not check something, but when I remove it so it checks and it sees some incompatibility.

To Aswer your question. I have seen using new operator to create instances from abstract class, however I am not aware if copy constructor is forbidden. I think it should not be problem to use it.
Last edited on
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
struct Base
{
  void foo(); // concrete function
  virtual void bar(); // virtual function
  virtual void gaz() = 0; // pure virtual function. This makes Base abstract
};

void Base::foo() {} // implementation required
void Base::bar() {} // implementation required
// there is no implementation for pure virtuals, as stated by "= 0"

struct Derived : public Base
{
  void foo();  // concrete function, masks Base::foo()
  void bar(); // virtual function, overrides Base::bar()
  void gaz(); // virtual function, overrides Base::gaz()
};
void Derived::foo() {} // implementation required
void Derived::bar() {} // implementation required
void Derived::gaz() {} // implementation required

int main()
{
  Base a; // error, Base is abstract
  Base * x = new Base; // error, Base is abstract
  Derived b; // ok
  Base * p = &b; // ok, Derived IS-A Base

  b.foo(); // calls Derived::foo()
  b.bar(); // calls Derived::bar()
  b.gaz(); // calls Derived::gaz()

  p->foo(); // calls Base::foo()
  p->bar(); // calls Derived::bar()
  p->gaz(); // calls Derived::gaz()

  return 0;
}
Pages: 123