我为我的子类类型库存新建了一个内存,它继承自基类工具,当我尝试访问我的数组的第二个元素时,它会抛出错误。当我的新数组大小为1
时,情况很好#include <iostream>
#include <fstream>
#include <string>
using namespace std;
class Instrument{
public:
virtual void display(){}
virtual void output(){}
virtual void readFile(){}
virtual ~Instrument(){}
};
class Stock :
public Instrument{
public:
Stock(){
}
virtual void input(){
cout << "This is stock, please input its information: ";
cin >> name >> bidPrice >> askPrice >> lastPrice >> issueExchange;
}
virtual void display(){
cout <<"This is to display stock: "<< name << " "
<< bidPrice << " "
<< askPrice << " "
<< lastPrice << " "
<< issueExchange << " "
<< endl;
}
virtual void output(){
ofstream myfile;
myfile.open("Stock.txt", ios::out | ios::app);
if (myfile.is_open()){
myfile << "This is a stock: "
<< name << " "
<< bidPrice << " "
<< askPrice << " "
<< lastPrice << " "
<< issueExchange << " "
<< endl;
}
else cout << "Unable to open file";
}
virtual void readFile(){
string line;
ifstream myfile("Stock.txt");
cout << "\nThis is file stored\n";
if (myfile.is_open())
{
while (getline(myfile, line))
{
cout << line << '\n';
}
myfile.close();
}
}
virtual ~Stock(){}
private:
char name[13];
double bidPrice;
double askPrice;
double lastPrice;
int issueExchange;
};
int main(){
const int N = 5;//it works fine if I use N=1;
Instrument *pBase = NULL;
pBase = new Stock[N];
for (int i = 0; i < N; i++){
pBase[i].input();// here throws an exception and ends the program
pBase[i].display();
pBase[i].output();
}
pBase[N - 1].readFile();
delete[] pBase;
system("pause");
return 0;
}
答案 0 :(得分:7)
多态性和指针算法不会混合,因为数组中对象的排列取决于最大的派生大小,而多态性会丢失该信息。动态分配是一个红色的鲱鱼,你可以看到同样的问题:
Derived array[2];
Base* p = array;
printf("%p\n", &array[0]);
printf("%p\n", p);
printf("%p\n", &array[1]);
printf("%p\n", p + 1);
printf("%z\n", sizeof (array[0]));
printf("%z\n", sizeof (*p));
请注意,使用array
的指针值向前移动sizeof (Derived)
,但使用p
的指针算法向前移动sizeof (Base)
而未找到真实对象。< / p>
通常,您可以使用Base*
数组来修复此问题,而不是将单个Base*
与指针算法结合使用。
Base* pp[2];
for( auto& elem : array ) pp[&elem - array] = &elem;
printf("%p\n", &array[1]);
printf("%p\n", pp[1]);
// use (*pp[1]) or pp[1]->whatever
另一种选择是使用记住原始类型的对象:
Derived* allocated = new Derived[N];
std::function<Base& (int)> poly = [allocated](int i){ return allocated[i]; };
并使用poly(i)
代替p[i]
但是警告,你不能delete [] &poly(0);
,因为delete[]
也不是多态的。
使用std::unique_ptr<Derived[]>
和std::bind
,当访问者对象最终超出范围时,可以安排自动释放。
答案 1 :(得分:1)
虽然Mr.Ben的方法是绝对正确的,但我完全觉得他的C ++和我的C ++不是同一种语言,他在这里混合了一些奇怪的东西,因此根据他的想法,我试图像这样修改我的代码
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <memory>
using namespace std;
class Instrument{
public:
virtual void display() = 0;
virtual void output() = 0;
virtual void readFile() = 0;
virtual ~Instrument(){};
};
class Stock :
public Instrument{
public:
Stock(){
cout << "This is stock, please input its information: ";
cin >> name >> bidPrice >> askPrice >> lastPrice >> issueExchange;
}
virtual void display(){
cout << "This is to display stock: " << name << " "
<< bidPrice << " "
<< askPrice << " "
<< lastPrice << " "
<< issueExchange << " "
<< endl;
}
virtual void output(){
ofstream myfile;
myfile.open("Stock.txt", ios::out | ios::app);
if (myfile.is_open()){
myfile << "This is a stock: "
<< name << " "
<< bidPrice << " "
<< askPrice << " "
<< lastPrice << " "
<< issueExchange << " "
<< endl;
}
else cout << "Unable to open file";
}
virtual void readFile(){
string line;
ifstream myfile("Stock.txt");
cout << "\nThis is file stored\n";
if (myfile.is_open())
{
while (getline(myfile, line))
{
cout << line << '\n';
}
myfile.close();
}
}
virtual ~Stock(){}
private:
string name;
double bidPrice;
double askPrice;
double lastPrice;
int issueExchange;
};
class Option :
public Instrument{
public:
Option(){
cout << "This is option, please input its information: ";
cin >> name >> uname >> bidPrice >> askPrice >> lastPrice >> contractSize >> exp;
}
virtual void display(){
cout << "This is to display option: "
<< name << " "
<< uname << " "
<< bidPrice << " "
<< askPrice << " "
<< lastPrice << " "
<< contractSize << " "
<< exp << " "
<< endl;
}
virtual void output(){
ofstream myfile;
myfile.open("Option.txt", ios::out | ios::app);
if (myfile.is_open()){
myfile << "This is an option: "
<< name << " "
<< uname << " "
<< bidPrice << " "
<< askPrice << " "
<< lastPrice << " "
<< contractSize << " "
<< exp << " "
<< endl;
}
else cout << "Unable to open file";
}
virtual void readFile(){
string line;
ifstream myfile("Option.txt");
cout << "\nThis is file stored\n";
if (myfile.is_open())
{
while (getline(myfile, line))
{
cout << line << '\n';
}
myfile.close();
}
}
virtual ~Option(){}
private:
string name;
string uname;
double bidPrice;
double askPrice;
double lastPrice;
int contractSize;
double exp;
};
class Future :
public Instrument{
public:
Future(){
cout << "This is option, please input its information: ";
cin >> name >> uname >> bidPrice >> askPrice >> lastPrice >> contractSize >> tickSize >> contractMonth;
}
virtual void display(){
cout << "This is to display option: "
<< name << " "
<< uname << " "
<< bidPrice << " "
<< askPrice << " "
<< lastPrice << " "
<< contractSize << " "
<< tickSize << " "
<< contractMonth << " "
<< endl;
}
virtual void output(){
ofstream myfile;
myfile.open("Future.txt", ios::out | ios::app);
if (myfile.is_open()){
myfile << "This is a future: "
<< name << " "
<< uname << " "
<< bidPrice << " "
<< askPrice << " "
<< lastPrice << " "
<< contractSize << " "
<< tickSize << " "
<< contractMonth << " "
<< endl;
}
else cout << "Unable to open file";
}
virtual void readFile(){
string line;
ifstream myfile("Future.txt");
cout << "\nThis is file stored\n";
if (myfile.is_open())
{
while (getline(myfile, line))
{
cout << line << '\n';
}
myfile.close();
}
}
virtual ~Future(){}
private:
string name;
string uname;
double bidPrice;
double askPrice;
double lastPrice;
int contractSize;
int tickSize;
int contractMonth;
};
int main(){
int N = 20;
//shared_ptr<Instrument> pBase[N];
vector<shared_ptr<Instrument>> pBase(N);
int i = 5;
for (i = 0; i < N; i++) pBase[i] = make_shared<Stock>();
for (i = 0; i < N; i++){
pBase[i]->display();
pBase[i]->output();
}
pBase[N - 1]->readFile();
for (i = 0; i < N; i++) pBase[i] = make_shared<Option>();
for (i = 0; i < N; i++){
pBase[i]->display();
pBase[i]->output();
}
pBase[N - 1]->readFile();
for (i = 0; i < N; i++) pBase[i] = make_shared<Future>();
for (i = 0; i < N; i++){
pBase[i]->display();
pBase[i]->output();
}
pBase[N - 1]->readFile();
system("pause");
return 0;
}
答案 2 :(得分:0)
tl;博士回答:不要将子类数组(Stock[N]
)转换为基类指针(pBase
)。直接使用Stock*
,或者创建一个指针数组:
auto arr = new Stock*[N];
for (int i = 0; i < N; i++) {
arr[i] = new Stock();
}
// unrelated but suggested: C++11 unique_ptr is recommended:
vector<unique_ptr<Stock>> v(N);
详细原因:
1)数组括号运算符是一个语法糖:a[b] -> *(a + b)
;
2)指针算法不是多态的,它总是基于静态类型:
pBase[i] -> *(pBase+i) -> *(pBase*)((char*)pBase + sizeof(Instrument) * i);
3)然而,这是你想要的:
pBase[i] -> *(pBase+i) -> *(pBase*)((char*)pBase + sizeof(Stock) * i);
4)只要sizeof(Instrument) != sizeof(Stock)
,你就遇到了麻烦。