Use of virtual functions

Hi all.This is my assingment(i am translating from Serbian):I have one class Workflow which has array of pointers type Step and length of array as private members(and some other functions).I have abstract class Step,and two derived classes from Step:State and activity.In main I have to make Workflow W1 of 2018 Steps from which half is type Activity and half is type State.Then I create Workflow W3 where i move all Steps type activity.at end I test operator=.This is my code.
Workflow.cpp
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
68
69
70
71
72
73
74
75
76
 Workflow::Workflow()
{
}

Workflow::Workflow(int a) {
	duz = a;
	Step **p = new Step*[duz];

}
Workflow::~Workflow() {
	delete[] p;

}
Workflow::Workflow(const Workflow &w)
{
	p = w.p;
	duz = w.duz;
}
void Workflow::InsertAt(int k)//This part i don't know
{
	const char *a;
Step *f;
	a = p[0]->Tip();
	int i;
	this->duz++;
	for (i = this->duz; i > k; i--)
		p[i] = p[i - 1];
	
	p[k] =f;//Why Can't I insert pointer type Step here
	this->duz++;
}
void Workflow::RemoveAt(int k)
{

	int i;
	for (i = k + 1; i <this->duz; i++)
		p[i] = p[i - 1];
	this->duz--;
}
Step** Workflow::GetSpecificSteps(const char *tip)
{//This function return pointers type Step an all steps of type Activity or State
int a;
	
	a=this->duz;
	Step **niz = new Step*[a];
	int i;
	if (tip != "Activity" || tip != "Steps")
		cout << "Pogresan unos u funkciju,unesite Activity ili Steps kao parametar" << endl;
	if (tip=="Activity")
		niz = new Step*[a];
	for (i = 0; i < a; i++)
		niz[i]->GetSpecAttribute();//This function returns type int
	if(tip="Steps")





	
	return niz;
}

int Workflow::Returnd()
{
	return duz;
}

ostream  &operator<<(ostream & out,const Workflow w)// i ovo pitati
{
	Step **p = new Step*[w.duz];
	for (int i = 0; i < w.duz; i++)
		out << p[i] << ',';


	return out;
}

Workflow.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
 #include"Step.h"
#include"State.h"
#include"Activity.h"

class Workflow {
private:
	int duz;
	Step **p;


public:
	Workflow();
	Workflow(int a=0);
	~Workflow();
	Workflow(const Workflow &w);
	void InsertAt(int k);
	void RemoveAt(int k);
	Step** GetSpecificSteps(const char* tip);
	int Returnd();
	friend ostream& operator<<(ostream& out, const Workflow w);
};

Step.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
 #pragma once
#include<iostream>
#include<ctime>
using namespace std;
class Step
{
protected:
	char* naziv;
	const char* tip;
public:
	char *	Vrati() { return naziv; }
	const char* Tip() { return tip; }
	Step();
	virtual ~Step();
	virtual int GetSpecAttribute() = 0;
	virtual void Prikazi();
};

Step.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include "Step.h"



Step::Step()
{
}

Step::~Step()
{
	delete[]naziv;
	delete[]tip;
}

 void Step::Prikazi()
{

	cout << naziv << ", " << tip << ", " << this->GetSpecAttribute() << endl;

}


Activity
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
 #pragma once
// NEsto mora da se stavi
#include"Step.h"
class Activity:public Step
{
	short int a;// a can be only one or zero
public:
	Activity();
	friend istream& operator>>(istream &in, Activity &a);
	virtual int GetSpecAttribute();
};

Activity::Activity()
{

	tip = "Activity";
	srand(time(NULL));
	a = rand() %2;
}

int Activity::GetSpecAttribute()
{
	return a;
}

istream& operator>>(istream &in, Activity &a)
{

	in >> a.a;
	in >> a.naziv;
	return in;

}

State
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
 #pragma once
#include"Step.h"
class State:public Step
{
	int prioritet;
public:
	State();
	State(int a);
	friend istream& operator>>(istream &in, State &s);
	virtual int GetSpecAttribute();
};

State::State()
{
	tip = "State";
	srand(time(NULL));
		prioritet = rand() % 300;
}
State::State(int a)
{
	prioritet = a;
	tip = "State";
}

int State::GetSpecAttribute()
{
	return prioritet;
}

istream& operator>>(istream& in, State &s)
{

	in>> s.prioritet;
	return in;
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
 #include <iostream>
#include <string>
#include"Workflow.h"
using namespace std;
int main()
{
	Workflow *work = new Workflow(2018);
	for (int i = 0; i < 1009; i++)
	{
		Activity *activity = new Activity();
		State *state = new State();
		


	}


	delete work;
	return 0;
}

my code so far
I have problem with GetSpecific Steps function ,insertAt(i can't insert a pointer ) and in main i dont know what to do next.
Last edited on
First thing: replace
1
2
3
4
class Workflow {
private:
	int duz;
	Step **p;

with
1
2
3
class Workflow {
private:
	std::vector<Step*> steps;

Rationale: you have more than enough to cope with the Step class hierarchy. Keep the other parts as simple as possible.

Your output operator makes no sense. I might write:
1
2
3
4
5
std::ostream& operator<< ( std::ostream& out, const Workflow & w )
{
  for ( auto step : w.steps ) out << step->Prikazi();
  return out;
}



The insert ... wish I knew what you really need to do there. A guess:
1
2
3
4
5
6
7
void Workflow::InsertAt( size_t k, Step* s )
{
  if ( k < steps.size() ) {
    if ( steps[k] ) delete steps[k];
    steps[k] = s;
  }
}
At insert a put a Step pointer on k position in array of pointers,is it possible to stay **Step because in classes we must use that and later to use it to call GetSpecAttribut from derived classes with polymorphism.I know I shoud use step pointers to somehow point to Activity and step function GetSpecAttribut.
My bad. This is closer, but not complete:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
void Workflow::InsertAt( size_t k, Step* s )
{
  if ( duz == capacity ) {
    // Array is full. Should we allocate more space or what?
    return;
  }

  if ( k > duz ) {
    // There would be unused space between previous steps and k
    // How to handle that?
  }
  else {
    int last = duz;
    while ( k < last ) {
      p[last] = p[last-1];
      --last;
    }
    ++duz;
    p[k] = s;
  }
}


That could allow:
1
2
3
4
5
6
7
8
int main()
{
  Workflow work( 2 );
  work.InsertAt( 0, new Activity );
  work.InsertAt( 0, new State );
  std::cout << work;
  return 0;
}
Last edited on
k is an index of array element so we won't nee to check if k is longer than array size.Thanks for your help .I appreciate it very much.
k is an index of array element so we won't nee to check if k is longer than array size.

Yes and no.

What is duz?

When you create a Workflow, you set duz to something and allocate an array that has duz elements.

How many Steps are in the Workflow at that point? 0. None. You have not inserted any yet.

You insert one Step. How many steps are there now? 1
How many elements are in the array? duz, unless you reallocate.
However, in your original code you increment the duz.

You have two options:
1. Keep track of both the size of the array and the count of Steps in it. Then you do need two variables: duz and something. That is how std::vector works.

2. The size of array is exactly the count of Steps at all times. When you create a Workflow, the duz==0 and array has no elements. Every time you insert, you must allocate larger array and copy all Steps. Every time you remove, you should shrink the array.
duz is like length of array .I have a constructor that sets length and allocates memory for length Step pointers.I think like when we allocate memory there is a array of length Step pointers that can point to State or Activity.So at that moment we are not using them.But with function GetSpecAttribute I think i make them point to one of the derived classes
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Step** Workflow::GetSpecificSteps(const char *type)//ponovo deklarisati
{
int a;
	
	a=this->duz;
	Step **array = new Step*[a];
	int i;
	if (type != "Activity" || type != "Steps")
		cout << "Bad input in Fuction,please input Ac << endl;
	if (type=="Activity")
		
	for (i = 0; i < a; i++)
		array[i] = new Activity;
	if(type="State")
		for (i = 0; i < a; i++)
			array[i] = new State;

	return array;
} 
Last edited on
1. You can't compare C-strings like that. C library has a function for comparing strings. The alternative is to use std::string, which does have operator== (and operator!=).

2. I do get the impression that GetSpecificSteps() should return an array of steps of specific type that are already in the workflow.
1
2
3
4
5
GetSpecificSteps of type:
  // count elements that are of type
  // create new array for them
  // copy elements of type from workflow into the new array
  // return the new array 
Last edited on
Topic archived. No new replies allowed.