size_t
for mat.cols
and mat.rows
memcpy()
to copy data. Element assignment has a lower efficiency(float *)
nor 2D array (float **)
for matrix datamatrix.h
#ifndef _MATRIX_H
#define _MATRIX_H
#include "stdbool.h" // for bool
#include "stdlib.h"
typedef struct Matrix_{ // use typedef to simplify type name
size_t rows; // use size_t, not int
size_t cols; // use size_t, not int
float * data;
}Matrix;
Matrix * createMat(size_t rows, size_t cols);
bool releaseMat(Matrix * p);
bool add(const Matrix * input1, const Matrix * input2, Matrix *output);
#endif
matrix.c
#include
#include
#include "matrix.h"
// return NULL if failed
Matrix * createMat(size_t rows, size_t cols)
{
Matrix * p = NULL;
if (rows == 0 || cols == 0)
{
fprintf(stderr, "rows and/or cols is 0.\n"); // 错误打印到标准错误输出,可以通过管道把错误信息导到不同的文件
return NULL;
}
// allocate memory
p = (Matrix *) malloc(sizeof(Matrix));
if (p == NULL)
{
fprintf(stderr, "Failed to allocate memory for a matrix.\n");
return NULL;
}
p->rows = rows;
p->cols = cols;
p->data = (float *) malloc(p->rows * p->cols * sizeof(float));
if (p->data == NULL)
{
fprintf(stderr, "Failed to allocate memory for the matrix data. \n");
free(p); // Don't forget to free memory here;
return NULL;
}
return p;
}
bool releaseMat(Matrix * p)
{
// don't forget to check a pointer before using it
if (!p) return false;
if (p->data) free(p->data);
free(p);
return true;
}
bool add(const Matrix * input1, const Matrix * input2, Matrix * output)
{
// You must check all parameters carefully first
// It's important, and can save a lot of time on debugging
if (input1 == NULL)
{
// use stderr for error messages
fprintf(stderr, "File %s, Line %d, Function %s(): The 1st parameter is NULL. \n",
__FILE__, __LINE__, __FUNCTION__);
return false;
}
else if (input1->data == NULL)
{
fprintf(stderr, "%s(): The 1st parameter has no valid data. \n", __FUNCTION__);
return false;
}
if (input2 == NULL)
{
// use stderr for error messages
fprintf(stderr, "File %s, Line %d, Function %s(): The 2nd parameter is NULL. \n",
__FILE__, __LINE__, __FUNCTION__);
return false;
}
else if (input2->data == NULL)
{
fprintf(stderr, "%s(): The 2nd parameter has no valid data. \n", __FUNCTION__);
return false;
}
if (output == NULL)
{
// use stderr for error messages
fprintf(stderr, "File %s, Line %d, Function %s(): The 3rd parameter is NULL. \n",
__FILE__, __LINE__, __FUNCTION__);
return false;
}
else if (output->data == NULL)
{
fprintf(stderr, "%s(): The 3rd parameter has no valid data. \n", __FUNCTION__);
return false;
}
if (input1->rows != input2->rows || input2->rows != output->rows ||
input1->cols != input2->cols || input2->cols != output->cols)
{
fprintf(stderr, "The input and the output do not match. They should have the same size. \n");
fprintf(stderr, "Their sizes are(%zu, %zu), (%zu, %zu) and (%zu, %zu)",
input1->rows, input1->cols,
input2->rows, input2->cols,
output->rows, output->cols);
return false;
}
// version1, the best one
size_t length = input1->rows * input1->cols;
const float * p1 = input1->data;
const float * p2 = input2->data;
float *p3 = output->data;
for(size_t i = 0; i<length; i++)
{
*(p3++) = *(p1++) + *(p2++);
}
// version2, better one
for (size_t r = 0; r < input1->rows; r++)
{
// to calculate (col*r) herre, don't put it into the inner loop
const float *p1 = input1->data + input1->cols * r;
const float *p2 = input2->data + input2->cols * r;
float *p3 = output->data + output->cols * r;
for (size_t c = 0; c < input1->cols; c++)
{
*(p3++) = *(p1++) + *(p2++);
}
}
// version3, a bad one
for(size_t r = 0; r < input1->rows; r++)
{
for (size_t c = 0; c < input2->cols; c++)
{
output->data[output->cols * r + c] =
input1->data[input1->cols * r + c] +
input2->data[input2->cols * r + c];
}
}
return true;
}
main.c
#include
#include "matrix.h"
int main()
{
Matrix * matA = createMat(2, 3);
Matrix * matB = createMat(2, 3);
Matrix * matC = createMat(2, 3);
Matrix * matD = createMat(3, 2);
Matrix * matNULL = NULL;
//initialization
// You should have your own method to do it
matA->data[3] = 2.3f;
matB->data[3] = 3.1f;
if( !add(matA, matB, matC))
{
fprintf(stderr, "Mayrtix addition failed.");
}
else{
// You can have a metter method to show the results
printf("result=%f\n", matC->data[3]);
}
// more tests
add(matA, matB, matD);
add(matNULL, matB, matC);
return 0;
}
gcc *.c
./a.out
result=5.400000
The input and the output do not match. They should have the same size.
Their sizes are(2, 3), (2, 3) and (3, 2)File matrix.c, Line 58, Function add(): The 1st parameter is NULL.
(1) Base class (parent)
(2) Derived class (child)
class Base
{
public:
int a;
int b;
};
class Derived: public Base
{
public:
int C;
};
class Derived: public Base1, public Base2
{
...
};
构造函数在子类中怎么执行
(1) Allocate memory
(2) Derived constructor is invoked:
[1] Base object is constructed by a base constructor
[2] Member initializer list initializes members
[3] To execute the body of the derived constructor
class Derived: public Base
{
public:
int c;
Derived(int c): Base(c - 2, c - 1), c(c)
{
...
}
};
derived.cpp
#include
using namespace std;
class Base
{
public:
int a;
int b;
Base(int a = 0, int b = 0)
{
this->a = a;
this->b = b;
cout << "Constructor Base::Base(" << a << ", " << b << ")" << endl;
}
~Base()
{
cout << "Destructor Base::~Base()" << endl;
}
int product()
{
return a * b;
}
friend std::ostream & operator<<(std::ostream & os, const Base & obj)
{
os << "Base: a = " << obj.a << ", b = " << obj.b;
return os;
}
};
class Derived: public Base
{
public:
int c;
Derived(int c): Base(c - 2, c - 1), c(c)
{
this->a += 3; //it can be changed after initialization
cout << "Constructor Derived::Derived(" << c << ")" << endl;
}
~Derived()
{
cout << "Destructor Derived::~Derived()" << endl;
}
int product()
{
return Base::product() * c;
}
friend std::ostream & operator<<(std::ostream & os, const Derived & obj)
{
// call the friend function in Base class
os << static_cast<const Base&>(obj) << endl;
os << "Derived: c = " << obj.c;
return os;
}
};
int main()
{
{
Base base(1, 2);
cout << "Product = " << base.product() << endl;
cout << base << endl;
}
cout << "----------------------" << endl;
{
Derived derived(5);
cout << derived << endl;
cout << "Product = " << derived.product() << endl;
}
return 0;
}
Constructor Base::Base(1, 2)
Product = 2
Base: a = 1, b = 2
Destructor Base::~Base()
----------------------
Constructor Base::Base(3, 4)
Constructor Derived::Derived(5)
Base: a = 6, b = 4
Derived: c = 5
Product = 120
Destructor Derived::~Derived()
Destructor Base::~Base()
class Person{
private:
int n; // private member
public:
// this->n is accessible
Person() : n(10) {} // initialization
// other.n is accessible
Person(const Person& other): n(other.n) {} // Copy constructor
// this->n is accessible
void set(int n) {this->n = n;}
// this->n and other.n are accessible
void set(const Person& other) {this->n = other.n; }
};
Accessible to the members and friends of that class
class Base
{
protected:
int n;
private:
void fool(Base& b)
{
n++; // Okay
b.n++; // Okay
}
};
Accessible to the members and friends of the derived class
class Derived : public Base
{
void foo2(Base& b, Derived& d)
{
n++; // Okay
this->n++; // Okay
b.n++; // Error
d.n++; // Okay
}
};
// a non-member non-friend function
void compare(Base& b, Derived& d)
{
b.n++; // Error
d.n++; // Error
}
(1) Still be public in the derived class
(2) Accessible anywhere
(1) Still be protected in the derived class
(2) Accessible in the derived class only
(1) Not accessible in the derived class
可以通过父类公有函数去访问
(1) Be protected in the derived class
(2) Accessible in the derived class only
(1) Not accessible in the derived class
(1) Be private in the derived class
(2) Accessible in the derived class only
(1) Not accessible in the derived class
class Person
{
public:
void print()
{
cout << "Name: " << name << endl;
}
};
class Student: public Person
{
public:
void print()
{
cout << "Name: " << name;
cout << ". ID: " << id << endl;
}
};
Person *p = new Student();
p->print(); // call Person:print()?
子类和父类有同样的函数,调用子类的对象的函数,会调用子类还是父类定义的函数?
virtual.cpp
#include
#include
using namespace std;
class Person
{
public:
string name;
Person(string n): name(n){}
void print()
{
cout << "Name: " << name << endl;
}
};
class Student: public Person
{
public:
string id;
Student(string n, string i): Person(n), id(i){}
void print()
{
cout << "Name: " << name;
cout << ". ID: " << id << endl;
}
};
void printObjectInfo(Person & p)
{
p.print();
}
int main()
{
{
Student stu("yu", "2019");
printObjectInfo(stu);
}
{
Person * p = new Student("xue", "2020");
p->print(); //if print() is not a virtual function, different output
delete p; //if its destructor is not virtual
}
return 0;
Name: yu
Name: xue
调用的都是父类的函数,而这个对象是子类的对象,我们希望对于子类的对象调用子类定义的函数,结果还是调用的父类的函数
virtual
就可以实现多态#include
#include
using namespace std;
class Person
{
public:
string name;
Person(string n): name(n){}
void print()
{
cout << "Name: " << name << endl;
}
};
class Student: public Person
{
public:
string id;
Student(string n, string i): Person(n), id(i){}
void print()
{
cout << "Name: " << name;
cout << ". ID: " << id << endl;
}
};
void printObjectInfo(Person & p)
{
p.print();
}
int main()
{
{
Student stu("yu", "2019");
printObjectInfo(stu);
}
{
Person * p = new Student("xue", "2020");
p->print(); //if print() is not a virtual function, different output
delete p; //if its destructor is not virtual
}
return 0;
}
Name: yu. ID: 2019
Name: xue. ID: 2020
为什么?
print()
function as a virtual function, the output will be differentStatic
binding: the compiler decides which function to callDynamic
binding: the called function is decided at runtime参考:C++虚函数表剖析
class Person2
{
public:
string name;
Person2(string n): name(n){}
virtual void print() = 0;
};
Person * p = new Student("xue", "2020");
p->print();
...
...
delete p; // if its destructor is not virtual
析构函数一定是虚函数
class MyMap: public MyString
{
private:
char * keyname;
MyMap(const char * key, const char * value)
{
...
}
MyMap(const MyMap & mm): MyString(mm.buf_len, mm.characters)
{
//allocate memory for keyname
//and hard copy from mm to *this
}
MyMap & operator=(const MyMap &mm)
{
MyMap::operator=(mm);
//allocate memory for keyname
//and hard copy from mm to *this
return *this;
}
};
cv::Mat_
cv::Mat
, a wrapper, more C++ styleMat_
类比Mat
类更加C++化cv::Matx
cv::Vec