I am trying ot add a function template that will print if it contains precision values or valves and the value. The rest of the program works except this function. I am not sure what I am doing wrong but the error I recieve is:
error C2784: 'void printInstrumentDetail(const I *const )' : could not deduce template argument for 'const I *const ' from 'std::vector<_Ty>'
#include <iostream>
#include <vector>
#include <iomanip>
#include <string>
#include "Instruments.h"
#include "Brass.h"
#include "Strings.h"
using namespace std;
//template<typename I> <---Problem
//void printInstrumentDetail(const I * const a)
//{
// for (size_t i = 0; i < 6; i ++)
// {
// cout << "The details for " << a[i]->getName()
// << ": " << a[i]->print();
// }
//}
int main()
{
double total = 0;
Strings violin("Violin", 553.90, 3);
Strings cello("Cello", 876.45, 3);
Strings viola("Viola", 200.50, 23);
Brass tuba("Tuba", 1400.10, 1.23);
Brass trumpet("Trumpet", 500.00, 4.32);
Brass sax("Sax", 674.78, .99);
vector <Instruments *> band(6);
band[0] = &violin;
band[1] = &tuba;
band[2] = &cello;
band[3] = &trumpet;
band[4] = &viola;
band[5] = &sax;
cout << fixed << setprecision(2);
cout << "The instruments in the band are:\n";
//Get name and cost of each
for (size_t i = 0; i < 6; i ++)
{
cout << band[i]->getName() << " $"
<< band[i]->getCost() << endl;
}
cout << "\nThen band is warming up..." << endl;
//Get descrition of how sound is made of each
for (size_t i = 0; i < 6; i ++)
{
cout << "This " << band[i]->getName()
<< " makes sounds by " ;
band[i]->playSound();
}
cout << "\nTotal cost of the band is: $" ;
//Get total cost of all instruments
for (size_t i = 0; i < 6; i ++)
{
total = band[i]->getCost() + total;
}
cout << total << endl;
//printInstrumentDetail(band); <--Problem
return 0;
}
Here's the base class:
#ifndef INSTRUMENTS_H
#define INSTRUMENTS_H
#include <string>
using namespace std;
class Instruments
{
public:
Instruments(string, double);
void setName(string);
virtual string getName();
void setCost(double);
virtual double getCost();
virtual void print();
virtual void playSound();
private:
string name;
double cost;
};
#endif
#include <iostream>
#include "Instruments.h"
using namespace std;
Instruments::Instruments(string n, double c)
{
name = n;
cost = c;
}
void Instruments::setName(string n)
{
name = n;
}
string Instruments::getName()
{
return name;
}
void Instruments::setCost(double c)
{
cost = c;
}
double Instruments::getCost()
{
return cost;
}
void Instruments::print()
{
}
void Instruments::playSound()
{
//empty
}
Derived class Bass:
#ifndef BRASS_H
#define BRASS_H
#include <string>
#include "Instruments.h"
using namespace std;
class Brass : public Instruments
{
public:
Brass(string, double, double);
void setPrecisionValue(double);
double getPrecisionValue();
void print() ;
void playSound();
private:
double precision;
string sound;
};
#endif
#include <iostream>
#include "Brass.h"
using namespace std;
Brass::Brass(string n, double c, double p)
:Instruments(n, c)
{
precision = p;
}
void Brass::setPrecisionValue(double p)
{
precision = p;
}
double Brass::getPrecisionValue()
{
return precision;
}
void Brass::print()
{
cout << getPrecisionValue() << endl;
}
void Brass::playSound()
{
cout << "blowing in a mouthpiece." << endl;
Instruments::playSound();
}
Derived class Strings:
#ifndef STRINGS_H
#define STRINGS_H
#include <string>
#include "Instruments.h"
using namespace std;
class Strings : public Instruments
{
public:
Strings(string, double, int);
void setValves(int);
int getValves();
void print();
void playSound();
private:
int valves;
};
#endif
#include <iostream>
#include "Strings.h"
using namespace std;
Strings::Strings(string n, double c, int v)
:Instruments(n, c)
{
valves = v;
}
void Strings::setValves(int v)
{
valves = v;
}
int Strings::getValves()
{
return valves;
}
void Strings::print()
{
cout<< getValves() << endl;
}
void Strings::playSound()
{
cout << "striking with a bow." << endl;
Instruments::playSound();
}
Well, the problem is that your template requires a pointer:
template<typename I>
void printInstrumentDetail(const I * const a);
but you're giving it a vector, not a pointer:
vector <Instruments *> band(6);
...
printInstrumentDetail(band);
You can hack your way around this by passing a pointer to the printInstrumentDetail function, like so:
printInstrumentDetail(&band[0]);
But really, you'd be much better off modifying printInstrumentDetail to take a container or a pair of iterators:
template <typename ContainerT>
void printInstrumentDetail(const ContainerT& a)
or
template <typename IteratorT>
void printInstrumentDetail(IteratorT first, IteratorT last)
with the appropriate modifications to the definition of the function.
Pass the pointer to vector
printInstrumentDetail(&band);
and inside printInstrumentDetail
(*a)[i]->getName();
Well, first off I don't believe you can pass a vector as a const * I const at
printInstrumentDetail(band);
Vector cannot be just cast to a pointer. One working solution would be something like:
template <typename T>
void printInstrumentDetail( const std::vector<T*>& band )
{
for ( size_t i = 0; i < band.size(); ++i )
cout << "The details for " << band[i]->getName()
<< ": " << band[i]->print();
}
And there are many others, including iterators, functors, STL algorithms, etc.
You are trying to pass an object to an interface that wants a pointer.
void printInstrumentDetail(const I * const a)
Convert this to a reference.
void printInstrumentDetail(I const I& a)
But to conform to the pattern that is common in C++. You should pass the beginning and end of the sequence as parameters. ie change your function to take itertors rather than a pointer.
Instead of passing the pointer:
printInstrumentDetail(const I * const a)
you can pass the reference:
printInstrumentDetail(const I& a)
Everything else stays unchanged.
First of all, there seems to be no reason for PrintInstrumentDetail to be a template at all -- it works with pointers to the base class, and unless you're likely to have other types with getName() and print() members to which it might be applied, it can/could/should just work with pointers to the base class.
Second, I'd think hard about changing how you do the job. Instead of a member function in each Instrument, and PrintInstrumentDetail to loop over all the instruments, I'd think hard about defining operator<< for Instrument, and using a standard algorithm to print out the details.
Looking at it, I think a few other things should change as well. First of all, unless you're dealing with really unusual instruments, the number of valves on a brass instrument is fixed forever -- so it should NOT have a SetValve() member. Rather, the number of valves should be set during construction, but not be open to change afterwards.
String instruments don't have valves at all (at least most normal ones don't), so they shouldn't have SetValves(), GetValves(), or anything else related to valves.
Likewise, unless you're doing something pretty unusual, the cost of an instrument can never change -- you paid what you paid, so the cost should be set during construction, and not open to later alteration.
Edit: one other thing: instead of hard-coding 6 everywhere, use band.size() to loop over all the instruments in the band.
Related
This has been driving me insane for hours - I'm new to C++: I can't figure out why my programs thinks I want it do this.
I have a class House
class House{
private:
int number;
std::string family;
public:
House(int n, std::string f){
this->number = n;
this->family = f;
}
House(){
this->number = 0;
this->family = "unassigned";
}
void whoLivesHere(){
std::cout<<"The"<<family<<"lives here."<<std::endl;
}
};
I have another class Neighborhood
class Neighborhood{
private:
int size;
House houses[100];
public:
Neighborhood(){
this->size=0;
}
void addHouse(House h){
this->houses[this->size] = h;
this->size++;
}
void whoLivesHere(){
for(int i=0; i<this->size; i++){
this->houses[this->size].whoLivesHere();
}
}
};
And this is what is happening on my main.
int main(){
Neighborhood n1;
House h1(1,"Johnsons");
House h2(1,"Jones");
n1.addHouse(h1);
n1.addHouse(h2);
n1.whoLivesHere();
return 0;
}
And what I get on the Terminal is this.
The unassigned lives here
The unassigned lives here
The unassigned lives here
Why didn't the new objects replace the first two default objects?
Why show three objects? If size should be 1.
Thank you tonnes in advance!
You can make short work of this problem by using the tools the C++ Standard Library gives you, like this:
#include <string>
#include <vector>
#include <iostream>
int main() {
std::vector<House> neighborhood;
// emplace_back() forwards arguments to the constructor
neighborhood.emplace_back(1, "Johnson");
neighborhood.emplace_back(2, "Jones");
// No need to track size, std::vector does that for you: size(),
// but that's not even needed to iterate, you can just do this:
for (auto& house : neighborhood) {
house.whoLivesHere();
}
return 0;
}
Here I've cleaned up your House implementation:
class House {
private:
int number;
std::string family;
public:
// Tip: Use constructor lists
House(int n, const std::string& f) : number(n), family(f) { };
// Useful even for defaults
House() : number(0), family("unassigned") { };
// Flag methods that don't modify anything as const
void whoLivesHere() const {
std::cout << "The " << family << " lives here at number " << number << "." << std::endl;
}
};
I would like to return an array to a pointer, in a virtual function that is a member of a derived class of a template class. In details, my classes definition is:
Sampler.h
#ifndef SAMPLER_H
#define SAMPLER_H
template <class T>
class Sampler
{
public:
virtual T getnumber()=0;
virtual T* simulation(int n)=0;
};
class UniformSampler:public Sampler<double>
{
public:
virtual double getnumber();
virtual double* simulation(int n);
UniformSampler(double a=0.0, double b=1.0);
private:
double low_bound;
double up_bound;
};
#endif
The class Sampler is a template class in order to be able to derive an other sampler with vectors later. The implementation is:
Sampler.cpp
#include "Sampler.h"
#include<iostream>
#include<cstdlib>
#include<cmath>
using namespace std;
//Uniform
UniformSampler::UniformSampler(double a, double b)
{
low_bound=a;
up_bound=b;
}
double UniformSampler::getnumber()
{
int myrand=rand();
while((myrand==0)||(myrand==RAND_MAX)){myrand = rand(); } //We want a number in (0, RAND_MAX).
double myuni = myrand/static_cast<double>(RAND_MAX); //Create a number in (0,1).
return low_bound + myuni*(up_bound-low_bound);
}
double* UniformSampler::simulation(int n){
double simulations[n];
for(int i=0; i<n; i++){
simulations[i] = this->getnumber();
}
return simulations;
}
My problem is that, when I try to call this program in the main(), it looks like the assignment of the pointer doesn't work. Here is my main.cpp:
#include <iostream>
#include <math.h>
#include <cstdlib>
#include <time.h>
using namespace std;
#include "Sampler.h"
int main(){
srand(time(0));
int n=10;
double *unif = new double[n];
UniformSampler uni;
unif = uni.simulation(n);
for ( int i = 0; i < n; i++ ) {
cout << "*(p + " << i << ") : ";
cout << *(unif + i) << endl;
}
delete[] unif;
return 0;
}
When I run it, it doesn't print any of the elements that unif points to. I don't understand what is wrong there.
UniformSampler::simulation is twice wrong:
double simulations[n]; uses VLA extension, so not C++ standard compliant.
you return pointer on local variable, so dangling pointer.
Solution: use std::vector instead.
#include <vector>
template <class T>
class Sampler
{
public:
virtual ~Sampler() = default;
virtual T getnumber() = 0;
virtual std::vector<T> simulation(int n) = 0;
};
class UniformSampler:public Sampler<double>
{
public:
explicit UniformSampler(double a=0.0, double b=1.0);
double getnumber() overrid;
std::vector<double> simulation(int n) override
{
std::vector<double> res(n);
for (auto& val : res){
res = getnumber();
}
return res;
}
private:
double low_bound;
double up_bound;
};
int main(){
srand(time(0));
constexpr int n = 10;
UniformSampler uni;
auto unif = uni.simulation(n);
for (int i = 0; i < n; i++ ) {
std::cout << "p[" << i << "]: " << unif[i] << endl;
}
}
I am new to classes and am having a lot of difficulty with the constructors. I have two constructors for a business class and whenever I attempt to create a business object or do anything with the business object I immediately Seg Fault. The business class interacts with an additional class called Customer. If anyone could offer any help I would greatly appreciate it.
Business.h
#ifndef BUSINESS_H
#define BUSINESS_H
#include <iostream>
#include <string>
#include "customer.h"
using namespace std;
class Business
{
public:
Business();
Business(string name, float cash);
void printData() const;
void addCustomer(Customer newCustomer);
void make_a_sale();
private:
string businessName;
float cashInReg;
string itemArray[10];
Customer custInBus[10];
short numOfItems;
short numOfCustom;
};
#endif
Business.cpp
#include "business.h"
#include <iostream>
#include <cstdlib>
using namespace std;
Business::Business(): businessName("Business"), cashInReg(0), numOfItems(0),
numOfCustom(0) {}
Business::Business(string name, float cash) : businessName(name),
cashInReg(cash), numOfCustom(0) {}
void Business::printData() const
{
cout << businessName <<endl;
for (int i=0; i<numOfCustom; i++)
{
cout << "\t Customer Name: " << custInBus[i].getName() <<endl;
}
for (int i=0; i<numOfItems; i++)
{
cout << "\t Item list: " <<itemArray[i] <<endl;
}
}
void Business::addCustomer(Customer newCustomer)
{
custInBus[numOfCustom-1] = newCustomer;
numOfCustom++;
}
void Business::make_a_sale()
{
int randomItem;
int currCustomer=0;
while (currCustomer < numOfCustom)
{
randomItem = rand() %tempItems;
custInBus[currCustomer].purchase(tempArray[randomItem]);
currCustomer ++;
}
}
void Business::addCustomer(Customer newCustomer)
{
custInBus[numOfCustom] = newCustomer;
//use numOfCustom instead of numOfCustom-1
numOfCustom++;
}
I have one application in which following task are to be done
1.) UI application will send command code (integer value).
2.) DLL interface(in c++) will get that integer value and execute corresponding command function.
commands name and command code are maintained as
#define PING 50
there will be 500 commands and applying SWITCH CASE will not sound good. so i decided to implement function pointer in my code as below
#include "stdafx.h"
#include<iostream>
#define PING 20
using namespace std;
//extern const int PING = 10;
void ping()
{
cout<<"ping command executed";
}
void get_status(void)
{
cout<<"Get_status called"<<endl;
}
class ToDoCommands
{
public:
void getCommand( void (*CommandToCall)() );
};
void ToDoCommands::getCommand( void (*CommandToCall)())
{
void (*CommandToCall1)();
CommandToCall1 = CommandToCall;
CommandToCall1();
}
int main()
{
int code;
ToDoCommands obj;
cout<<"enter command code";
cin>>code; // if UI send 50 then Ping function get executed as #define PING 50
obj.getCommand(ping); // here m passing ping manually..
//obj.getCommand(get_status);
return 0;
}
how can i pass command name corresponding to command code in
obj.getCommand(ping);
You are almost there: make a std::map of std::string to function pointer, initialize it with data pairing a string name to a corresponding function pointer, and then use that map at runtime to pick the correct pointer based on the string parameter passed in.
#include <iostream>
#include <string>
#include <map>
using namespace std;
void ping() {
cout << "ping" << endl;
}
void test() {
cout << "test" << endl;
}
int main() {
map<string,void(*)()> m;
m["ping"] = ping;
m["test"] = test;
// I am using hard-coded constants below.
// In your case, strings will come from command line args
m["test"]();
m["ping"]();
return 0;
}
Link to a demo with std::map.
Here is how you can do it without a map (it will be slower because of the linear search, but you can fix it by ordering names alphabetically and using binary search).
#include <iostream>
#include <cstring>
using namespace std;
void ping() {
cout << "ping" << endl;
}
void test() {
cout << "test" << endl;
}
typedef void (*fptr_t)();
int main() {
const fptr_t fptrs[] = {test, ping};
const char *names[] = {"test", "ping"};
const char *fname = "test";
for (int i = 0 ; i != 2 ; i++) {
if (!strcmp(fname, names[i])) {
fptrs[i]();
break;
}
}
return 0;
}
Link to a demo with arrays.
Declare an array of function pointers. Where you treat the index as your "code". For example:
void foo(){
printf("foo\n");
}
void bar(){
printf("bar\n");
}
int main(void)
{
void (*code_to_function[100])();
int code;
code_to_function[0] = foo;
code_to_function[1] = bar;
printf("Enter code: ");
scanf("%d", &code);
code_to_function[code]();
return 0;
}
Please note that for this rudimentary example, inputting integer code other than 0 and 1 will result in a segfault.
I should say #dasblinkenlight is right but if you don't want to use std::map you should implement a map yourself. This can be buggy and not a optimized way, but if you don't want to use STL, it seems you should implement it yourself.
You can use 2 arrays with corresponding indices. One of them is a char * array and another one is function pointers. They are better to be encapsulated in a class named something like MyMap.
class MyMap {
public:
...
inline void add(char *name, (void (*ptr)(void)) ) {
names_[currIndex_] = name; // Or stcpy
ptrs_[currIndex_] = ptr;
currIndex_++;
}
inline (void(*)(void)) get(char *name) {
int foundIndex = -1;
for (int i = 0; i < currIndex_; i++) {
// Find matching index
}
if (foundIndex_ >= 0) {
return ptrs_[foundIndex_];
}
return NULL;
}
private:
int currIndex_;
char *names_[10];
(void (*ptrs_[10])(void));
};
I have a class for performing various array operations. I like to use my insert method in my populate method.
Can someone guide me on that? Here is the code:
#include <iostream>
#include <cstdlib>
using namespace std;
const int MAX=5;
class array
{
private:
int arr[MAX];
public:
void insert(int pos, int num);
void populate(int[]);
void del(int pos);
void reverse();
void display();
void search(int num);
};
void array::populate(int a[])
{
for (int i=0;i<MAX;i++)
{
arr[i]=a[i];
}
}
void array::insert(int pos, int num)
{
for (int i=MAX-1;i>=pos;i--)
{
arr[i] = arr[i-1];
arr[i]=num;
}
}
void array::del(int pos)
{
for (int i=pos;i<MAX;i++)
{
arr[pos]=arr[pos + 1];
}
}
void array::display()
{
for (int i=0;i<MAX;i++)
cout<<arr[i];
}
void array::search(int num)
{
for (int i=0;i<MAX;i++)
{
if (arr[i]==num)
{
cout<<"\n"<<num<<" found at index "<<i;
break;
}
if (i==MAX)
{
cout<<num <<" does not exist!";
}
}
}
int main()
{
array a;
for (int j=0;j<MAX;j++)
{
a.insert(j,j);
}
a.populate(a);
a.insert(2,7);
a.display();
a.search(44);
system("pause");
}
I like to use my insert method in my
populate method. Can someone guide me
on that?
That would mean that instead of the straightforward and efficient "copy from one array to another" approach, you'd call insert for each value of the input with the correct index in place of the assignment.
To call a method on the current instance, from inside a method:
insert(x, y);
//or
this->insert(x, y);
Your code also contains an error, in that you pass a wrong type to populate in main. It expect int* (a real array), not an array object.
Please elaborate your question. If you just need a good container have a look at the STL (Standard Template Library) std::vector. It's part of the C++ standard and comes with your compiler.
If you want to learn how to write a custom class, please try to be more precise in your question.
Also consider the wealth of beginner tutorials available on the net, for example:
http://www.learncpp.com/
Here is a little example on how to write a custom class with one member function calling the other and accessing a private data member (note that inside a member function you can refer to any other member directly):
#include <iostream>
class Example
{
private:
int some_private_stuff;
public:
Example();
void function_a();
void function_b();
};
Example::Example(){
some_private_stuff = 1;
}
void Example::function_a(){
std::cout << "this is function a" << std::endl;
some_private_stuff = 2;
std::cout << "changed private_stuff to " << some_private_stuff << std::endl;
}
void Example::function_b(){
std::cout << "this is function b" << std::endl;
function_a();
}
int main() {
Example e;
e.function_b();
return 0;
}