12.4 总结

1、Link Error 和 Compile Error

1) Link阶段发生的错误(文件本身complie没有问题,但是互相链接阶段的问题。例如声明了函数但是没有找到主体、库文件的错误以及互相引用的问题等。)

*error以LNK开头
在这里插入图片描述

2) Complie阶段的问题。(某个文件本身的问题,可能是语法等)

error以C开头
在这里插入图片描述

2、头文件中函数定义:使用inline 或者 static

#include相当于复制过去,如果在一个头文件A.h中定义函数B,其他多个文件都使用了#include"A.h",那B函数就会出现多次定义的LNK错误。(always have a body in xx,but… )

解决办法:
1)只在头文件中写函数声明,函数body写入其他函数。
2)在函数前加static,相当于该函数为本文件私有使用,不对外可见。所有使用该函数的文件相当于都单独拥有一份该函数的内部定义。
3)在函数前加inline,内联函数相当于直接在函数引用中替换值。

3、Inline 内联函数

  1. 隐式内联、显式内联
    定义在类内的函数都是隐式内联函数,显示内联需要增加关键字inline

参考:隐式内联函数和显式内联函数

**隐式内联**

using namespace std;

class A

{

public:

    void func(int x,int y){i=x;j=y;}     //成员函数func()是内联函数

    void print(){cout<<"两数相乘为:"<<i*j<<endl;}  //成员函数print()是内联函数

private:

    int i,j;

};

int main()

{

    A a;

    a.func(1,2); //调用func(1,2)内联函数等于直接将i=1,j=2写在这里

    a.print(); //调用print()内联函数等于将"cout<<"两数相乘为:"<<i*j<<endl;"直接写到该行

    return 0;

}

2)不是所有的函数都适合定义为inline,因为inline是以代码复制、即增加内存消耗为代价换取代码运行速度的(无需调用函数而是直接复制替换)。
①使用次数过多的,每次都复制,内存消耗量++
②本身inline函数中消耗就较大的,不适合。比如当内部有循环体时,执行函数体的循环要比调用函数的花销更大。

参考:inline那些事

4、C++类型转换及其!!极其!!不智能

一定要注意数据类型不同时的转换丢失情况。bool 、int、float、double它是一点不会转!!!
另外,注意output里面warning的信息,很可能就是最后导致error的地方!没报错是因为语法上对,逻辑上和实际严格检查上不一定对。
在这里插入图片描述

编译器报错的滞后性:

很可能报错在n行,实际出错在n-1行,报错位置比真正出错的位置滞后一行。
例如:在第7行缺少分号,但在编译第8行时才会发现第7行有错,因此报错在8行。记得debug时检查上一行内容。

5、判断点是否在三角形内部

法1:一般程序都用同侧法,即将三角形三边看作有方向的AB、BC、CA,看Q点是否在三条边的同侧。

图1
新的问题,如何判断两个点在一条线的同侧?——右手螺旋定则!
在这里插入图片描述
根据向量的叉乘以及右手螺旋定则,ABxAM (x表示叉乘,这里向量省略了字母上面的箭头符号)的方向为向外指出屏幕,ABxAN也是向外指出屏幕,但ABxAO的方向是向内指向屏幕,因此M,N在直线AB的同侧,M ,O在直线AB的两侧。实际计算时,只需要考虑叉积的数值正负
假设以上各点坐标为A(0,0), B(4,0), M(1,2), N(3,4), O(3,-4), 则:

ABxAM = (4,0)x(1,2) = 42 - 01 = 8

ABxAN = (4,0)x(3,4) = 44 – 03 = 16

ABxAO = (4,0)x(3,-4) = 4*-4 – 0*3 = –16

回到三角形内外的判断中来,以Q点图为例。判断Q点:
flag1=ABxAQ
flag2=BCxBQ
flag3=CAxCQ
3个flag同号则在内部,异号则在外部。

PS:点乘(意义是cos)可以用于判断角度是否大于90°,大于为负,小于为正

//ours_1
static bool insideTriangle(int x, int y, const Vector3f* _v)
{   
    // TODO : Implement this function to check if the point (x, y) is inside the triangle represented by _v[0], _v[1], _v[2]                          
    
    //p
    Eigen::Vector3f v0p = { _v[0].x() - x,_v[0].y() - y,1.0f };
    Eigen::Vector3f v1p = { _v[1].x() - x,_v[1].y() - y,1.0f };
    Eigen::Vector3f v2p = { _v[2].x() - x,_v[2].y() - y,1.0f };
    //v
    Eigen::Vector3f v0v1 = { _v[0].x() - _v[1].x(),_v[0].y() - _v[1].y(),1.0f };
    Eigen::Vector3f v1v2 = { _v[1].x() - _v[2].x(),_v[1].y() - _v[2].y(),1.0f };
    Eigen::Vector3f v2v0 = { _v[2].x() - _v[0].x(),_v[2].y() - _v[0].y(),1.0f };

    float flagv0v1 = v0p.cross(-v2v0).z();
    float flagv1v2 = v1p.cross(-v0v1).z();
    float flagv2v0 = v2p.cross(-v1v2).z();

    if (flagv0v1>0) {
        return  flagv1v2>0 && flagv2v0>0;
    }
    else {                                          
        return flagv1v2<0 && flagv2v0<0;
    }
        
}
法2:自向量乘法,其实跟上一个方法的核心思想一样,但是计算量小,中间变量也更小

flag1=QAxQB
flag2=QBxQC
flag3=QCxQA
同号内部,异号外部

static bool insideTriangle(int x, int y, const Vector3f* _v){

    Eigen::Vector3f pv0 = { x - _v[0].x() ,y- _v[0].y() ,1.0f };
    Eigen::Vector3f pv1 = { x - _v[1].x() ,y - _v[1].y() ,1.0f };
    Eigen::Vector3f pv2 = { x - _v[2].x() ,y - _v[2].y() ,1.0f };

    if (pv0.cross(pv1).z()>0 ) {
        return  pv1.cross(pv2).z() > 0 && pv2.cross(pv0).z() > 0;
    }
    else {
        return pv1.cross(pv2).z() < 0 && pv2.cross(pv0).z() < 0;
    }

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值