EDIT: I basically revamped the whole question so I could provide an executable example...
I have been getting a segmentation fault that I can't figure out. Here is a compacted version of my code. I maintained the original class hierarchy even though some of the classes have no relevant methods since I think that it has something to do with my issue, especially after some of the comments I've been getting.
#import <vector>
using namespace std;
template<class Data = float>
class Vector
{
// All pure virtual functions.
};
template<class Data>
class TranslationVector : public virtual Vector<Data>
{
// All pure virtual functions.
};
template<class Data>
class SimpleVector4 : public virtual Vector<Data>
{
public:
SimpleVector4(const Data d0, const Data d1, const Data d2, const Data d3)
{
fData = new vector<Data> ;
fData->push_back(d0);
fData->push_back(d1);
fData->push_back(d2);
fData->push_back(d3);
}
vector<Data>*
getData()
{
return (fData);
}
private:
vector<Data>* fData;
};
template<class Data>
class SimpleTranslationVector4 : public SimpleVector4<Data> , public TranslationVector<Data>
{
public:
SimpleTranslationVector4(const Data x, const Data y, const Data z, const Data w) :
SimpleVector4<Data> (x, y, z, w)
{
}
};
template<class Data = float>
class Matrix
{
// All pure virtual functions.
};
template<class Data>
class TransformationMatrix : public virtual Matrix<Data>
{
// All pure virtual functions.
virtual void
translate(TranslationVector<Data>* const translation) = 0;
};
template<class Data>
class SimpleMatrix44 : public virtual Matrix<Data>
{
public:
SimpleMatrix44()
{
fData = new vector<Data> (CELLS_IN_MATRIX, 0);
setIdentity();
}
vector<Data>*
getData()
{
return (fData);
}
void
setIdentity()
{
fData->at(0) = 1;
fData->at(1) = 0;
fData->at(2) = 0;
fData->at(3) = 0;
fData->at(4) = 0;
fData->at(5) = 1;
fData->at(6) = 0;
fData->at(7) = 0;
fData->at(8) = 0;
fData->at(9) = 0;
fData->at(10) = 1;
fData->at(11) = 0;
fData->at(12) = 0;
fData->at(13) = 0;
fData->at(14) = 0;
fData->at(15) = 1;
}
private:
static const int CELLS_IN_MATRIX = 16;
vector<Data>* fData;
};
template<class Data>
class SimpleTransformationMatrix44 : public SimpleMatrix44<Data> , public TransformationMatrix<Data>
{
public:
SimpleTransformationMatrix44() :
SimpleMatrix44<Data> ()
{
}
void
translate(TranslationVector<Data>* translation)
{
vector<Data> *data = SimpleMatrix44<Data>::getData();
vector<Data> *transData = ((SimpleVector4<Data>*) translation)->getData();
// The error occurs on this line:
data->at(12) += data->at(0) * transData->at(0) + data->at(4) * transData->at(1) + data->at(8) * transData->at(2);
data->at(13) += data->at(1) * transData->at(0) + data->at(5) * transData->at(1) + data->at(9) * transData->at(2);
data->at(14) += data->at(2) * transData->at(0) + data->at(6) * transData->at(1) + data->at(10) * transData->at(2);
data->at(15) += data->at(3) * transData->at(0) + data->at(7) * transData->at(1) + data->at(11) * transData->at(2);
}
};
int
main(int argc, char** argv)
{
SimpleTransformationMatrix44<float> matrix1;
matrix1.translate(new SimpleTranslationVector4<float> (0.0f, 10.0f, 0.0f, 1.0f));
return 0;
}
I have commented in the code where the error occurs. From debugging I can see that it actually occurs in the size() function of vector and that transData has not been initialized. I can't for the life of me figure out why transData has not been initialized! Any ideas?
Thanks,
Gaz.
Cast of non-inherited classes seems to be your error.
Let's see your code. There is a conversion of SimpleTranslationVector4<float>* to TranslationVector<float>* while invoking the translate function. Then the converted value is converted again into SimpleVector4<float>*. But the SimpleVector4<float> does not inherit TranslationVector<float>.
This code also results in error.
template<class Data>
class SimpleVector4 {
public:
int a;
};
template<class Data>
class TranslationVector {
};
template<class Data>
class SimpleTranslationVector4 : public SimpleVector4<Data>,
public TranslationVector<Data> {
};
int main() {
SimpleTranslationVector4<float> A;
SimpleVector4<float>* b = (SimpleVector4<float>*)&A;
TranslationVector<float>* c = (TranslationVector<float>*)&A;
SimpleVector4<float>* d = (SimpleVector4<float>*)c;
b->a = 1; // ok
d->a = 1; // error
}
You're doing a C-style cast between unrelated types. This is not safe. The fact that you need to do this at all probably indicates a problem in your design, but try replacing this:
vector<Data>* transData = ((SimpleVector4<Data>*) translation)->SimpleVector4<Data>::getData();
with this:
vector<Data>* transData = dynamic_cast<SimpleVector4<Data>*>(translation)->getData();
Related
I am new to QT started to try out some things with QMap as it seems like a useful tool. I already read some other forum threads but I wasnt able to answer my question. The user is supposed to add and edit different shapes via the GUI. For the shapes I first wrote an abstract base class:
#ifndef BASE_H
#define BASE_H
#include <QListWidget>
#include <QMap>
class Base
{
protected:
QVariantMap m_properties;
QString m_key;
void setKey(const QString& key){
this->m_key=key;
}
public:
Base(){}
virtual ~Base(){}
QString key(){
return m_key;
}
void setProperty(QString key, QVariant variant){
m_properties[key]=variant;
}
virtual void toRTC()=0;
};
#endif // BASE_H
one example of a subclass is an ellipse with the following cpp file:
#include "ellipse.h"
Ellipse::Ellipse(int Start_x, int Start_y, int Rad_x, int Rad_y): rad_x(Rad_x), rad_y(Rad_y), start_x(Start_x), start_y(Start_y)
{
this->setKey("ellipse");
this->setProperty("radX", rad_x);
this->setProperty("radY", rad_y);
this->setProperty("startX", start_x);
this->setProperty("startY", start_y);
}
void Ellipse::set_rad_x(int rad_x)
{
Base::setProperty("radX", rad_x);
}
void Ellipse::set_rad_y(int rad_y)
{
Base::setProperty("radY", rad_y);
}
void Ellipse::set_start_x(int start_x)
{
Base::setProperty("startX", start_x);
}
void Ellipse::set_start_y(int start_y)
{
Base::setProperty("startY", start_y);
}
int Ellipse::get_rad_x()
{
return m_properties["radX"].toInt();
}
int Ellipse::get_rad_y()
{
return m_properties["radY"].toInt();
}
int Ellipse::get_start_x()
{
return m_properties["startX"].toInt();
}
int Ellipse::get_start_y()
{
return m_properties["startY"].toInt();
}
First off, is this a correct approach for the cpp file? I feel my approach is vary laborious.
In my main window file I thought about storing my data in a simple Vector QVector<Base *> data_storage;
Ellipse *e_values = new Ellipse(ui->Ellipse_Value_start_x->value(),ui->Ellipse_Value_start_y->value(), ui->Ellipse_Value_rad_x->value(),ui->Ellipse_Value_rad_y->value());
data_storage.append(e_values);
To load the data, I thought it would be a good idea to use the key to check which object of data_storage I want to load, but I don't really know how I can access the data which is connected to my key.
if(data_storage[t]->key()=="ellipse"){
ui->Ellipse_Value_rad_x->setValue(data_storage[t]->) //how can I access the correct data?
}
I feel like I messed up the entire approach, like how to properly use keys, so how would I do that?
You need to declare all the behaviours you need in the base class. I don't see the need to have Base hold the data.
E.g. if you need to be able to read and write the UI, there should be methods to do that.
class Base
{
public:
virtual ~Base() = default;
virtual void toRTC() = 0;
virtual QVariantMap properties() const = 0;
virtual void writeUI(form_t * ui) const = 0;
virtual void readUI(const form_t * ui) = 0;
};
class Ellipse : public Base
{
int start_x;
int start_y;
int rad_x;
int rad_y;
public:
void toRTC() final { /* ??? */ }
QVariantMap properties() const final {
return { { "radX", rad_x }, { "radY", rad_y },
{ "startX", start_x }, { "startY", start_y } };
}
void writeUI(form_t * ui) const final {
ui->Ellipse_Value_rad_x->setValue(rad_x);
ui->Ellipse_Value_rad_y->setValue(rad_y);
ui->Ellipse_Value_start_x->setValue(start_x);
ui->Ellipse_Value_start_y->setValue(start_y);
}
void readUI(const form_t * ui) final {
rad_x = ui->Ellipse_Value_rad_x->value().toInt();
rad_y = ui->Ellipse_Value_rad_y->value().toInt();
start_x = ui->Ellipse_Value_start_x->value().toInt();
start_y = ui->Ellipse_Value_start_y->value().toInt();
}
};
If you don't want to tie your shapes to the UI, you could define a visitor interface, with a visit method for each shape type.
class ShapeVisitor
{
virtual void accept(Ellipse * ellipse) = 0;
/* virtual void accept(Rectangle * rectangle) = 0; // etc.. */
};
class Base
{
public:
virtual ~Base() = default;
virtual void toRTC() = 0;
virtual QVariantMap properties() const = 0;
virtual void visit(ShapeVisitor & visitor) = 0;
};
class Ellipse : public Base
{
public:
int start_x;
int start_y;
int rad_x;
int rad_y;
void toRTC() final { /* ??? */ }
QVariantMap properties() const final {
return { { "radX", rad_x }, { "radY", rad_y },
{ "startX", start_x }, { "startY", start_y } };
}
void visit(ShapeVisitor & visitor) final {
visitor.accept(this); // calls visitor::accept(Ellipse *)
}
};
class UIReadVisitor : public ShapeVisitor
{
form_t * ui
void accept(Ellipse * ellipse) final {
ellipse->rad_x = ui->Ellipse_Value_rad_x->value().toInt();
ellipse->rad_y = ui->Ellipse_Value_rad_y->value().toInt();
ellipse->start_x = ui->Ellipse_Value_start_x->value().toInt();
ellipse->start_y = ui->Ellipse_Value_start_y->value().toInt();
}
}
class UIWriteVisitor : public ShapeVisitor
{
form_t * ui;
void accept(Ellipse * ellipse) final {
ui->Ellipse_Value_rad_x->setValue(ellipse->rad_x);
ui->Ellipse_Value_rad_y->setValue(ellipse->rad_y);
ui->Ellipse_Value_start_x->setValue(ellipse->start_x);
ui->Ellipse_Value_start_y->setValue(ellipse->start_y);
}
}
Hi I am coding a synth in the Juce framework.
When my adsr is running I need to override isVoiceActive() and set it to true from inside the voice. This is a public member function of the SynthesiserVoice class.
virtual bool SynthesiserVoice::isVoiceActive ( ) const
Returns true if this voice is currently busy playing a sound.
By default this just checks the getCurrentlyPlayingNote() value, but
can be overridden for more advanced checking.
So in the voice I have another member function virtual void renderNextBlock() and from inside it I want to override isVoiceActive
class SynthVoice : public SynthesiserVoice
{
public:
void renderNextBlock (AudioBuffer <float> &outputBuffer, int startSample, int numSamples) override
{
for (int sample = startSample; sample < (startSample + numSamples); ++sample)
{
float env_value = adsr.getNextSample();
if(env_value > 0)
isVoiceActive = true; //???????
...
you cannot do this because isVoiceActive is not an attribute it's a function, you can use your isVoiceActive as a data member and not as a function member so you can assign it true or false. or if you want to work with function then you have to add '&' so you can assign to that function a value (if you don't use '&' then you cannot do what you want to do.
you have 2 choices:
1/ to use isVoiceActivat as a data member and you can do like this:
class SynthesiserVoice
{
public:
bool isVoiceActive;
};
class SynthVoice :public SynthesiserVoice
{
public:
oid renderNextBlock (AudioBuffer <float> &outputBuffer, int startSample, int numSamples) override
{
for (int sample = startSample; sample < (startSample + numSamples); ++sample)
{
float env_value = adsr.getNextSample();
if(env_value > 0)
isVoiceActive = true;
}
}
};
2/ to do the following:
class SynthesiserVoice
{
public:
bool i = false;
virtual bool& isVoiceActive() { return i; } // or virtual bool& isVoiceActive()=0;
};
class SynthVoice :public SynthesiserVoice
{
public:
bool& isVoiceActive()override { return i; }
void renderNextBlock (AudioBuffer <float> &outputBuffer, int startSample, int numSamples) override
{
for (int sample = startSample; sample < (startSample + numSamples); ++sample)
{
float env_value = adsr.getNextSample();
if(env_value > 0)
isVoiceActive ()= true;
}
}
};
Now you have to implement this to suit your functions and data.
Hope it's clear and helpful
I am creating a class that inherits another class and have constructor which is required to have a parameter - object of the base class -
My question is what do I do with that object how do I store it so I can access its attributes?
I am not supposed to create other attributes/containers like list<Baseclass> name
class TelephoneSub // Base class
{
private:
string ts_name;
string ts_country_code;
double ts_tariff_plan;
int ts_minutes_call;
public:
TelephoneSub(const TelephoneSub &p)
{
this->ts_name = p.ts_name;
this->ts_country_code = p.ts_country_code;
this->ts_tariff_plan = p.ts_tariff_plan;
this->ts_minutes_call = p.ts_minutes_call;
}
Derived class
class TelephoneSubData : public TelephoneSub
{
private:
string tsd_phone_number;
vector<TelephoneSubData>tsd_contacts;
list<TelephoneSubData>tsd_called_numbers;
public:
// 2.1
TelephoneSubData() {}
// 2.2
TelephoneSubData(const string number,const TelephoneSub &sub)
{
this->tsd_phone_number = number;
TelephoneSub::TelephoneSub(sub);
}
double average_sum()const
{
double sum = 0;
int i = 0;
for (auto x : tsd_called_numbers)
{
i++;
sum += x.get_ts_tariff_plan();
}
return sum / i;
}
I have one base class and I have 4 class derived.of course I write 2 class for example.
I created vector and fill it by objects of derived classes, then I want sort my vector base of area function. I want use operator overloading.
I define operator overloading but it not Completely!
please help me!
Thanks....
class Shape
{
public:
Shape() {}
virtual void draw() = 0;
virtual int area() = 0;
virtual void perimeter() = 0;
bool operator >(Shape * shape_one , Shape* shape_two )
{
return shape_one->area() > shape_two->area();
}
protected :
double height;
double width;
};
class Squar : public Shape
{
public:
Squar(int _width) {
width = _width;
}
void draw(){}
int area(){
return width * width;
}
void perimeter(){}
bool operator >(Squar * squar_one , Squar* squar_two )
{
return squar_one->area() > squar_two->area();
}
};
class Triangle : public Shape
{
public:
Triangle(int _width , int _height) {
width = _width;
height = _height;
}
void draw(){}
int area(){
return (width * height) / 2;
}
void perimeter(){}
bool operator >(Triangle * triangle_one , Triangle* triangle_two )
{
return triangle_one->area() > triangle_two->area();
}
};
int main()
{
Shape *rect = new Rectangular( 1 , 9);
Shape *squar = new Squar(5);
QVector <Shape *> list;
list.push_back(rect);
list.push_back(squar);
retuurn 0;
}
I understand answer the question.
add following code in base class :
bool operator <( Shape *item )
{
return this->area() < item->area();
}
and add following code in main :
std ::sort(list.begin() , list.end() ,[](Shape* ptr_l , Shape* ptr_r) { return *ptr_l < ptr_r;} );
This code is correct! :)
I have a big project where I faced a problem, which can be shortly formulated as following:
I had a class which is created temporally and used to process and modify some data (let's call it "worker"). Now I have two workers and two corresponding data formats. The data array can contain mixed data, how to make my programm automatically decide which worker class it should create and use for data processing? How to make this in the best way?
To illustrate this problem I wrote small example programm, which is analogical to my project.
#include <iostream>
#include <vector>
using namespace std;
const int NInputs = 10;
struct TOutput {
int i;
};
class TProcess {
public:
TProcess( const vector<TInput>& i ){ fInput = i; }
void Run();
void GetOutput( TOutput& o ) { o = fOutput; }
private:
vector<TInput> fInput;
TOutput fOutput;
};
#if 0
struct TInput {
int i;
};
class TWorker{
public:
void Init( int i ) { fResult = i; }
void Add( int i ) { fResult += i; }
int Result() { return fResult; }
private:
int fResult;
};
#else
struct TInput {
int i;
};
class TWorker {
public:
void Init( int i ) { fResult = i; }
void Add( int i ) { fResult ^= i; }
int Result() { return fResult; }
private:
int fResult;
};
#endif
void TProcess::Run() {
TWorker worker;
worker.Init(0);
for( int i = 0; i < fInput.size(); ++i )
worker.Add(fInput[i].i);
fOutput.i = worker.Result();
}
int main() {
vector<TInput> input(NInputs);
for ( int i = 0; i < NInputs; i++ ) {
input[i].i = i;
}
TProcess proc(input);
proc.Run();
TOutput output;
proc.GetOutput(output);
cout << output.i << endl;
}
The example is very simple, but that doesn't means that it's simply possible to transform it to one function --- it corresponds to big project. Therefore it is not possible to:
delete classes or functions, which already exists (but possible to modify them and create new)
make workers static or create only one copy of worker (each workers are temporary in many complicated functions and loops)
So how to modify it such that this will be something like this:
// TODO: TProcess declaration
struct TInput1 {
int i;
};
class TWorker1{
public:
void Init( TInput1 i ) { fResult = i; }
void Add( TInput1 i ) { fResult += i.i; }
int Result() { return fResult; }
private:
int fResult;
};
#else
struct TInput2 {
int i;
};
class TWorker2 {
public:
void Init( TInput2 i ) { fResult = i.i; }
void Add( TInput2 i ) { fResult ^= i.i; }
int Result() { return fResult; }
private:
int fResult;
};
void TProcess::Run() {
for( int i = 0; i < fInput.size(); ++i ) {
// TODO: choose and create a worker
worker.Add(fInput[i].i);
// TODO: get and save result
}
fOutput.i = worker.Result();
}
int main() {
vector<TInputBase> input(NInputs);
// TODO: fill input
TProcess proc(input);
proc.Run();
TOutput output;
proc.GetOutput(output);
cout << output.i << endl;
}
My initial idea was to use basic class and template functions, but there is no template virtual functions...
You've got the right idea with the vector<TInputBase> declaration in your second example -- you need to have a common base class for all inputs, and similarly for all workers:
class TInput {
}
class TInput1 : public TInput { ... }
class TInput2 : public TInput { ... }
class TWorker {
public:
void Init(TInput *input) = 0;
void Add(TInput *input) = 0;
int Result() = 0;
}
class TWorker1 : public TWorker { ... }
class TWorker2 : public TWorker { ... }
Note, however, that this means all workers can only take a TInput * as input and you will need to cast to the correct input class inside each worker class.
The simplest way to decide which worker class to use for a given input is to ask the input itself! You can have a virtual function in the input class that creates the right kind of worker:
class TInput {
virtual TWorker *createWorker() = 0;
}
class TInput1 : public TInput {
TWorker *createWorker() {
return new TWorker1();
}
}
class TInput2 : public TInput {
TWorker *createWorker() {
return new TWorker2();
}
}
If this is not possible for some reason, you can use typeid to determine the type of the input and create a corresponding worker instance.